# Exact Match Site ID MCP Connector This service exposes Exact Match Site ID data to MCP-compatible AI clients such as ChatGPT, Claude, Cursor, and other tools that can call MCP servers. ## Stack - TypeScript - Hono for HTTP routes - Official MCP SDK for MCP protocol handling - Zod for input validation - Laravel `data` as the source of truth ## Local Setup 1. Copy `.env.example` to `.env`. 2. Set `LARAVEL_API_BASE_URL` to the Laravel API base URL. 3. Set `LARAVEL_MCP_PROXY_TOKEN` to the same value configured in Laravel for `services.mcp_proxy.internal_token`. 4. Set `OAUTH_TOKEN_SECRET` to at least 32 random characters. 5. Install dependencies with `npm install`. 6. Start local development with `npm run dev`. The default local service URL is `http://localhost:8787`. ## Useful URLs - Health: `GET /health` - MCP endpoint: `POST /mcp` - OAuth authorization metadata: `GET /.well-known/oauth-authorization-server` - MCP metadata: `GET /.well-known/mcp-server` - Widget: `GET /widgets/site-id` ## Development Auth When `MCP_DEV_AUTH_ENABLED=true`, a local auth code can be created by calling: ```txt GET /oauth/dev/start?clerk_user_id=user_xxx ``` Production should replace this dev handoff with the real Exact Match/Clerk login callback. ## Local OAuth Test Flow Use this flow to test OAuth locally before connecting the server to ChatGPT Apps. 1. Make sure `.env` contains a local redirect allowlist: ```env OAUTH_ALLOWED_REDIRECT_URIS=http://localhost:8787/oauth/dev/callback MCP_DEV_AUTH_ENABLED=true ``` 2. Start the MCP server: ```powershell npm run dev ``` 3. Open the dev authorization URL with a real Clerk user id: ```txt http://localhost:8787/oauth/dev/start?clerk_user_id=user_xxx ``` The browser redirects to: ```txt http://localhost:8787/oauth/dev/callback?code=...&state=... ``` 4. Copy the `code` value from the callback response. 5. Exchange the code for an MCP access token: ```powershell $code = "paste-code-here" Invoke-RestMethod ` -Method Post ` -Uri "http://localhost:8787/oauth/token" ` -ContentType "application/x-www-form-urlencoded" ` -Body @{ grant_type = "authorization_code" client_id = "local-dev" redirect_uri = "http://localhost:8787/oauth/dev/callback" code = $code } ``` Successful response: ```json { "access_token": "...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "...", "scope": "site_id:read" } ``` Use `access_token` as: ```txt Authorization: Bearer ``` This token authenticates AI app requests into the MCP server. The MCP server still authenticates to Laravel separately with `LARAVEL_MCP_PROXY_TOKEN`.