{"id":30526893,"url":"https://github.com/willitscale/streetlamp-ai","last_synced_at":"2025-09-07T18:47:24.172Z","repository":{"id":307571958,"uuid":"1021138864","full_name":"willitscale/streetlamp-ai","owner":"willitscale","description":"Attribute router tooling for AI solutions","archived":false,"fork":false,"pushed_at":"2025-09-02T00:20:57.000Z","size":73,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-02T02:30:52.743Z","etag":null,"topics":["ai","composer","composer-package","http","mcp","php","php84","router"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/willitscale.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-17T00:31:38.000Z","updated_at":"2025-09-02T00:21:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"dd3f45bc-2f40-4a8c-8922-00e4497b5cdc","html_url":"https://github.com/willitscale/streetlamp-ai","commit_stats":null,"previous_names":["willitscale/streetlamp-ai"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/willitscale/streetlamp-ai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willitscale%2Fstreetlamp-ai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willitscale%2Fstreetlamp-ai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willitscale%2Fstreetlamp-ai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willitscale%2Fstreetlamp-ai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/willitscale","download_url":"https://codeload.github.com/willitscale/streetlamp-ai/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willitscale%2Fstreetlamp-ai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274080633,"owners_count":25219018,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","composer","composer-package","http","mcp","php","php84","router"],"created_at":"2025-08-27T01:09:58.526Z","updated_at":"2025-09-07T18:47:24.163Z","avatar_url":"https://github.com/willitscale.png","language":"PHP","readme":"# Streetlamp AI\n\nAttribute router tooling for AI solutions. A support framework for rapidly building MCP servers using attributes in PHP.\n\n## Table of Contents\n\n- [Getting Started](#getting-started)\n- [Defining your MCP Server](#defining-your-mcp-server)\n- [Defining Capabilities](#defining-the-mcp-capabilities-and-sub-capabilities)\n- [Defining Method Actions](#defining-method-actions)\n- [Usage Example](#usage-example)\n\n## Prerequisites\n\n- PHP 8.4 or higher\n- Composer\n\n# Getting started \n\nTo begin with you're going to need to add Streetlamp AI to your composer package with:\n\n```bash\ncomposer require willitscale/streetlamp-ai\n```\n\nThis will include Streetlamp and Streetlamp AI into your package.\n\n# Creating your first MCP Server\n\nI'd advise you to read through the documentation for [Streetlamp](https://github.com/willitscale/streetlamp) and getting a Streetlamp application up and running first.\nI'm going to skip what's covered in the Streetlamp documentation for getting setup.\n\n## Defining our MCP Server\n\nWhat we need to do first is to define our server, we can do this with the attribute `ModelContextProtocol` which will bootstrap an MCP server for us at the defined path provided.\nThe class we decorate with the `ModelContextProtocol` can have middleware applied to it as shown below.\n\n```php\n#[ModelContextProtocol('/mcp', McpVersion::LATEST, 'Streetlamp', '1.0.0', 'Client information')]\n#[Middleware(AuthMiddleware::class)]\nclass McpController\n{\n}\n```\n\nUnlike a standard controller within Streetlamp the requests are passed off to a catch-all method within the `McpHandler`.\nIf you would like to handle all requests yourself you can do so by extending the `McpHandler` and overriding the `call` method as shown below.\n\n```php\n#[ModelContextProtocol('/mcp', McpVersion::LATEST, 'Streetlamp', '1.0.0', 'Client information')]\n#[Middleware(AuthMiddleware::class)]\nclass McpController extends McpHandler\n{\n    public function call(\n        #[BodyParameter] Request $request,\n        #[HeaderParameter('Accept', true)] string $accept,\n        #[HeaderParameter('MCP-Protocol-Version', true)] string $mcpProtocolVersion,\n        #[HeaderParameter('MCP-Session-Id')] ?string $mcpSessionId = null\n    ): ResponseInterface {\n        ...\n    }\n}\n```\n\n## Defining the MCP Capabilities and Sub-Capabilities\n\nWith the server defined we now need to define what capabilities our server will offer.\nWe define capabilities by decorating a class with the `McpCapability` attribute and the corresponding capability. \nWithin out capabilities we can also define sub-capabilities by decorating a function with the attribute `McpSubCapability` to be used as a callback for that sub-capability.\n\n```php\n#[McpCapability(McpCapabilities::RESOURCES)]\nclass ResourcesCapability\n{\n    #[McpSubCapability(McpSubCapabilities::SUBSCRIBE)]\n    public function subscribe(): mixed\n    {\n        ...\n    }\n}\n```\n\nI'd advise to read through the [MCP Specification](https://modelcontextprotocol.io/specification/2025-06-18) to understand how to respond correctly to MCP clients.\n\n## Defining Method Actions\n\nWhen making requests to the MCP server you do so via JsonRpc requests which require a method.\nThis method gets mapped to a capability and then an action within that capability.\nTo define an action you decorate a method within a capability with the `McpAction` attribute as shown below.\n\n```php\n#[McpCapability(McpCapabilities::RESOURCES)]\nclass ResourcesCapability\n{\n    #[McpAction('list')]\n    public function resources(): array\n    {\n        return [\n            'resources' =\u003e [\n                ...\n            ] \n        ];\n    }\n    \n    #[McpAction('read')]\n    public function resources(): array\n    {\n        return [\n            'contents' =\u003e [\n                ...\n            ] \n        ];\n    }\n    \n    #[McpAction('templates/list')]\n    public function resources(): array\n    {\n        return [\n            'resourceTemplates' =\u003e [\n                ...\n            ] \n        ];\n    }\n}\n```\n\nResponses from the action function calls are wrapped in the JsonRpc `Response` object as the result.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwillitscale%2Fstreetlamp-ai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwillitscale%2Fstreetlamp-ai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwillitscale%2Fstreetlamp-ai/lists"}