|
| 1 | +--- |
| 2 | +name: mcp-server |
| 3 | +description: Model Context Protocol server that exposes Meridian backend services to LLM clients via a thin JSON-RPC adapter over gRPC |
| 4 | +triggers: |
| 5 | + - Connecting Claude or another LLM client to Meridian |
| 6 | + - Querying financial positions, postings, or saga causation trees from an AI assistant |
| 7 | + - Validating, planning, and applying economy manifests through a conversational interface |
| 8 | + - Simulating CEL expressions, saga scripts, or valuation dry-runs before deployment |
| 9 | + - Configuring Claude Desktop for local Meridian development |
| 10 | +instructions: | |
| 11 | + MCP Server is a thin JSON-RPC adapter that exposes Meridian's gRPC services to LLM clients |
| 12 | + using the Model Context Protocol (MCP 2024-11-05). |
| 13 | +
|
| 14 | + Key patterns: |
| 15 | + - Transport agnostic: stdio for CLI tools (Claude Desktop), SSE for browser-based clients |
| 16 | + - Tool categories: Read (no side effects), Simulate (dry-run), Write (state mutation) |
| 17 | + - Plan-before-apply safety: meridian_manifest_plan must precede meridian_manifest_apply |
| 18 | + - OAuth 2.1 with PKCE: optional, enabled via MCP_OAUTH_ENABLED=true for SSE mode |
| 19 | + - All logs go to stderr; stdout is reserved for the JSON-RPC protocol (stdio mode) |
| 20 | +--- |
| 21 | + |
| 22 | +# MCP Server |
| 23 | + |
| 24 | +Thin JSON-RPC adapter that exposes Meridian's backend services to LLM clients via the |
| 25 | +[Model Context Protocol](https://spec.modelcontextprotocol.io/) (MCP 2024-11-05). |
| 26 | + |
| 27 | +## Overview |
| 28 | + |
| 29 | +| Attribute | Value | |
| 30 | +|-----------|-------| |
| 31 | +| **Type** | Infrastructure (API Gateway) | |
| 32 | +| **Language** | Go | |
| 33 | +| **Protocol** | MCP 2024-11-05 | |
| 34 | +| **Transports** | stdio, SSE | |
| 35 | +| **Auth** | OAuth 2.1 with PKCE (optional, SSE only) | |
| 36 | +| **Standalone** | No (requires Meridian backend services via `MERIDIAN_API_URL`) | |
| 37 | + |
| 38 | +## Architecture |
| 39 | + |
| 40 | +The MCP server is a stateless adapter. It translates MCP JSON-RPC calls into gRPC requests |
| 41 | +against Meridian's backend services and returns structured results suitable for LLM consumption. |
| 42 | + |
| 43 | +```mermaid |
| 44 | +flowchart TB |
| 45 | + subgraph "MCP Clients" |
| 46 | + CD[Claude Desktop] |
| 47 | + CB[Claude.ai / Browser] |
| 48 | + CLI[CLI Tools] |
| 49 | + end |
| 50 | +
|
| 51 | + subgraph "MCP Server" |
| 52 | + ST[stdio Transport] |
| 53 | + SE[SSE Transport] |
| 54 | + TH[Tool Handlers] |
| 55 | + RH[Resource Handlers] |
| 56 | + PH[Prompt Handlers] |
| 57 | + OA[OAuth 2.1 PKCE] |
| 58 | + end |
| 59 | +
|
| 60 | + subgraph "Meridian Backend" |
| 61 | + CP[Control Plane] |
| 62 | + RD[Reference Data] |
| 63 | + PK[Position Keeping] |
| 64 | + FA[Financial Accounting] |
| 65 | + SA[Saga Admin] |
| 66 | + RC[Reconciliation] |
| 67 | + MI[Market Information] |
| 68 | + end |
| 69 | +
|
| 70 | + CD -->|JSON-RPC| ST |
| 71 | + CLI -->|JSON-RPC| ST |
| 72 | + CB -->|JSON-RPC + Bearer| SE |
| 73 | + SE <--> OA |
| 74 | +
|
| 75 | + ST --> TH |
| 76 | + SE --> TH |
| 77 | + TH --> RH |
| 78 | + TH --> PH |
| 79 | +
|
| 80 | + TH -->|gRPC| CP |
| 81 | + TH -->|gRPC| RD |
| 82 | + TH -->|gRPC| PK |
| 83 | + TH -->|gRPC| FA |
| 84 | + TH -->|gRPC| SA |
| 85 | + TH -->|gRPC| RC |
| 86 | + TH -->|gRPC| MI |
| 87 | +``` |
| 88 | + |
| 89 | +## Transport Modes |
| 90 | + |
| 91 | +### stdio (default) |
| 92 | + |
| 93 | +Used by Claude Desktop and CLI tools. The server reads JSON-RPC requests from stdin and writes |
| 94 | +responses to stdout. Logs are written to stderr to avoid corrupting the protocol channel. |
| 95 | + |
| 96 | +```bash |
| 97 | +MCP_TRANSPORT=stdio ./mcp-server |
| 98 | +``` |
| 99 | + |
| 100 | +### SSE |
| 101 | + |
| 102 | +Used by browser-based clients and network-accessible deployments. The server exposes two HTTP |
| 103 | +endpoints: |
| 104 | + |
| 105 | +| Endpoint | Purpose | |
| 106 | +|----------|---------| |
| 107 | +| `GET /sse` | Establishes the SSE stream for server-to-client messages | |
| 108 | +| `POST /message` | Receives client JSON-RPC requests | |
| 109 | + |
| 110 | +```bash |
| 111 | +MCP_TRANSPORT=sse MCP_SSE_PORT=8090 ./mcp-server |
| 112 | +``` |
| 113 | + |
| 114 | +## Environment Variables |
| 115 | + |
| 116 | +| Variable | Default | Purpose | |
| 117 | +|----------|---------|---------| |
| 118 | +| `MCP_TRANSPORT` | `stdio` | Transport mode: `stdio` or `sse` | |
| 119 | +| `MCP_SSE_PORT` | `8090` | HTTP port when using SSE transport | |
| 120 | +| `MCP_SERVER_NAME` | `meridian-mcp` | Server name reported in MCP initialize response | |
| 121 | +| `MCP_BASE_URL` | `http://localhost:8090` | Base URL for OAuth redirect URIs (SSE mode) | |
| 122 | +| `MCP_OAUTH_ENABLED` | `false` | Enable OAuth 2.1 PKCE flow for SSE transport | |
| 123 | +| `MCP_OAUTH_CLIENT_ID` | `meridian-mcp` | OAuth client ID advertised to clients | |
| 124 | +| `MCP_OAUTH_REDIRECT_URI` | `{MCP_BASE_URL}/oauth/callback` | OAuth redirect URI | |
| 125 | +| `MERIDIAN_API_URL` | - | gRPC address of the Meridian gateway (e.g., `localhost:9090`) | |
| 126 | +| `MERIDIAN_API_KEY` | - | Bearer token sent in the `Authorization` header on all outgoing gRPC calls | |
| 127 | +| `LOG_LEVEL` | `info` | Log verbosity: `debug`, `info`, `warn`, `error` | |
| 128 | + |
| 129 | +## OAuth 2.1 Configuration |
| 130 | + |
| 131 | +OAuth 2.1 with PKCE is optional and only applies to the SSE transport. When enabled, the server |
| 132 | +exposes authorization and token endpoints and requires clients to present a bearer token on the |
| 133 | +`/sse` and `/message` endpoints. |
| 134 | + |
| 135 | +Example configuration for a production SSE deployment: |
| 136 | + |
| 137 | +```bash |
| 138 | +MCP_TRANSPORT=sse |
| 139 | +MCP_SSE_PORT=8090 |
| 140 | +MCP_BASE_URL=https://mcp.example.com |
| 141 | +MCP_OAUTH_ENABLED=true |
| 142 | +MCP_OAUTH_CLIENT_ID=my-mcp-client |
| 143 | +MCP_OAUTH_REDIRECT_URI=https://mcp.example.com/oauth/callback |
| 144 | +``` |
| 145 | + |
| 146 | +OAuth endpoints exposed when `MCP_OAUTH_ENABLED=true`: |
| 147 | + |
| 148 | +| Endpoint | Purpose | |
| 149 | +|----------|---------| |
| 150 | +| `GET /oauth/authorize` | Authorization endpoint (PKCE challenge) | |
| 151 | +| `POST /oauth/token` | Token endpoint (code exchange) | |
| 152 | + |
| 153 | +The current implementation ships a passthrough token issuer and validator suitable for development. |
| 154 | +For production, configure a real JWT signer and validator. |
| 155 | + |
| 156 | +## Claude Desktop Configuration |
| 157 | + |
| 158 | +### stdio mode (recommended for local development) |
| 159 | + |
| 160 | +Add the following to your Claude Desktop configuration file |
| 161 | +(`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS): |
| 162 | + |
| 163 | +```json |
| 164 | +{ |
| 165 | + "mcpServers": { |
| 166 | + "meridian": { |
| 167 | + "command": "/path/to/mcp-server", |
| 168 | + "env": { |
| 169 | + "MCP_TRANSPORT": "stdio", |
| 170 | + "MERIDIAN_API_URL": "localhost:9090", |
| 171 | + "MERIDIAN_API_KEY": "pk_your_tenant_api_key", |
| 172 | + "LOG_LEVEL": "info" |
| 173 | + } |
| 174 | + } |
| 175 | + } |
| 176 | +} |
| 177 | +``` |
| 178 | + |
| 179 | +### SSE mode (for network-accessible deployments) |
| 180 | + |
| 181 | +```json |
| 182 | +{ |
| 183 | + "mcpServers": { |
| 184 | + "meridian": { |
| 185 | + "url": "http://localhost:8090/sse" |
| 186 | + } |
| 187 | + } |
| 188 | +} |
| 189 | +``` |
| 190 | + |
| 191 | +## Available Tools |
| 192 | + |
| 193 | +Tools are grouped into three categories: |
| 194 | + |
| 195 | +- **Read** -- Query state without side effects |
| 196 | +- **Simulate** -- Compute or preview without persisting changes |
| 197 | +- **Write** -- Mutate state (requires explicit confirmation in most clients) |
| 198 | + |
| 199 | +### Read Tools |
| 200 | + |
| 201 | +| Tool | Description | |
| 202 | +|------|-------------| |
| 203 | +| `meridian_economy_structure` | Returns a hierarchical summary of the tenant's economy: instruments, account types, valuation rules, sagas, and payment rails | |
| 204 | +| `meridian_instruments_list` | Lists instrument definitions with optional status filter (ACTIVE, DRAFT, DEPRECATED) | |
| 205 | +| `meridian_instrument_describe` | Returns full details for a specific instrument by code, including CEL validation expressions | |
| 206 | +| `meridian_sagas_list` | Lists saga workflow definitions with optional status filter and system saga exclusion | |
| 207 | +| `meridian_saga_describe` | Returns full details for a saga including its Starlark script; lookup by UUID or name | |
| 208 | +| `meridian_handlers_describe` | Returns saga triggers and account type CEL policies from the current manifest | |
| 209 | +| `meridian_market_data_query` | Lists market data sets or queries observations for a specific dataset code | |
| 210 | +| `meridian_manifest_history` | Paginated manifest version history with apply status and timestamps | |
| 211 | +| `meridian_causation_tree` | Fetches the full parent→child saga causation tree for a root saga ID | |
| 212 | +| `meridian_positions_query` | Queries financial position logs with optional account filtering | |
| 213 | +| `meridian_postings_query` | Queries ledger postings with optional date range and account filtering | |
| 214 | +| `meridian_saga_executions` | Queries saga definitions and execution status filtered by state | |
| 215 | +| `meridian_reconciliation_status` | Queries reconciliation cycle status and variance mismatches | |
| 216 | + |
| 217 | +### Simulate Tools |
| 218 | + |
| 219 | +| Tool | Description | |
| 220 | +|------|-------------| |
| 221 | +| `meridian_manifest_validate` | Validates a manifest JSON without applying it; returns errors with paths and suggestions | |
| 222 | +| `meridian_manifest_diff` | Compares two manifests and returns a structured change summary by section | |
| 223 | +| `meridian_cel_evaluate` | Evaluates a CEL expression against a named environment without persisting state | |
| 224 | +| `meridian_valuation_simulate` | Dry-runs a valuation to convert an input quantity to a valued amount; returns full calculation path | |
| 225 | +| `meridian_saga_simulate` | Dry-runs a Starlark saga script with all service calls stubbed; returns step-by-step execution trace | |
| 226 | + |
| 227 | +### Write Tools |
| 228 | + |
| 229 | +| Tool | Description | |
| 230 | +|------|-------------| |
| 231 | +| `meridian_manifest_plan` | Dry-runs a manifest apply, stores the result, and returns a `plan_hash` for use with apply | |
| 232 | +| `meridian_manifest_apply` | Applies a manifest that has been previously planned; requires the `plan_hash` from plan | |
| 233 | + |
| 234 | +The plan-before-apply workflow enforces a safety gate: `meridian_manifest_apply` rejects any |
| 235 | +manifest that was not first processed by `meridian_manifest_plan` in the same session. |
| 236 | + |
| 237 | +## Resources |
| 238 | + |
| 239 | +Resources provide context that the LLM can load on demand. Access them via `resources/read` with |
| 240 | +the resource URI. |
| 241 | + |
| 242 | +| URI | Name | Description | |
| 243 | +|-----|------|-------------| |
| 244 | +| `meridian://manifest/current` | Current Economy Manifest | The active economy manifest for the current tenant in YAML format | |
| 245 | +| `meridian://docs/starlark-guide` | Starlark Saga Development Guide | Reference guide for writing Starlark saga scripts, including service modules, CEL patterns, and compensation patterns | |
| 246 | +| `meridian://docs/cel-reference` | CEL Expression Reference | Reference guide for Common Expression Language used in validation rules, bucketing expressions, and precondition checks | |
| 247 | + |
| 248 | +The `meridian://manifest/current` resource requires `MERIDIAN_API_URL` to be configured. If the |
| 249 | +client is not configured, a placeholder message is returned. |
| 250 | + |
| 251 | +The Starlark and CEL documentation are embedded at compile time and available without a backend |
| 252 | +connection. |
| 253 | + |
| 254 | +## Prompts |
| 255 | + |
| 256 | +Prompts are guided workflow starters that prime the LLM for a specific task. Use `prompts/get` |
| 257 | +with the prompt name and any required arguments. |
| 258 | + |
| 259 | +| Prompt | Arguments | Description | |
| 260 | +|--------|-----------|-------------| |
| 261 | +| `design-economy` | — | Guided manifest creation workflow. Asks clarifying questions about instruments, account types, sagas, and valuation rules, then generates a complete manifest | |
| 262 | +| `audit-transaction` | `transaction_id` (required) | Investigates a transaction's causation tree: originating saga, position movements, journal entries, and compensation actions | |
| 263 | +| `simulate-change` | `change_description` (required) | Tests a proposed manifest change before applying; analyses impact on sagas, instruments, and account types | |
| 264 | +| `debug-saga` | `saga_id` (required) | Diagnoses a failed or stuck saga: execution log, failing step, compensation status, and remediation suggestions | |
| 265 | + |
| 266 | +## Local Development |
| 267 | + |
| 268 | +The MCP server is included in the Tilt local development stack. |
| 269 | + |
| 270 | +### Prerequisites |
| 271 | + |
| 272 | +- A running Meridian local cluster (see root `Tiltfile`) |
| 273 | +- Go 1.26+ for building locally outside of Tilt |
| 274 | + |
| 275 | +### Running with Tilt |
| 276 | + |
| 277 | +Start the full Meridian stack: |
| 278 | + |
| 279 | +```bash |
| 280 | +cd ~/dev/github.com/meridianhub/meridian/meridian-main |
| 281 | +tilt up |
| 282 | +``` |
| 283 | + |
| 284 | +The MCP server starts alongside the other services and connects to the local Meridian gateway. |
| 285 | + |
| 286 | +### Running standalone (stdio mode) |
| 287 | + |
| 288 | +Build and run directly against a running local cluster: |
| 289 | + |
| 290 | +```bash |
| 291 | +# From repo root |
| 292 | +go build -o /tmp/meridian-mcp ./services/mcp-server/cmd |
| 293 | + |
| 294 | +# Run in stdio mode |
| 295 | +MERIDIAN_API_URL=localhost:9090 \ |
| 296 | + MERIDIAN_API_KEY=pk_your_tenant_api_key \ |
| 297 | + LOG_LEVEL=debug \ |
| 298 | + /tmp/meridian-mcp |
| 299 | +``` |
| 300 | + |
| 301 | +### Running standalone (SSE mode) |
| 302 | + |
| 303 | +```bash |
| 304 | +MCP_TRANSPORT=sse \ |
| 305 | + MCP_SSE_PORT=8090 \ |
| 306 | + MERIDIAN_API_URL=localhost:9090 \ |
| 307 | + MERIDIAN_API_KEY=pk_your_tenant_api_key \ |
| 308 | + LOG_LEVEL=debug \ |
| 309 | + /tmp/meridian-mcp |
| 310 | +``` |
| 311 | + |
| 312 | +Then connect Claude Desktop using the SSE configuration above, or test with curl: |
| 313 | + |
| 314 | +```bash |
| 315 | +# Open SSE stream |
| 316 | +curl -N http://localhost:8090/sse |
| 317 | + |
| 318 | +# Send a tools/list request (in a separate terminal) |
| 319 | +curl -X POST http://localhost:8090/message \ |
| 320 | + -H 'Content-Type: application/json' \ |
| 321 | + -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' |
| 322 | +``` |
| 323 | + |
| 324 | +## References |
| 325 | + |
| 326 | +- [Services Architecture](../README.md) |
| 327 | +- [Control Plane Service](../control-plane/README.md) |
| 328 | +- [MCP Protocol Specification](https://spec.modelcontextprotocol.io/) |
0 commit comments