# Carrick docs: full text Concatenated text of every Carrick documentation page. Each section begins with a `# Title` heading and a canonical URL. Pages are ordered by their published reading order. --- # Introduction Source: https://docs.carrick.tools/introduction Updated: 2026-06-01 Carrick indexes every TypeScript service in your GitHub org and hands that index to your AI coding agent over MCP. Agents working across many repos burn most of their context grepping, guessing, and rebuilding code that already exists somewhere else in the org. Carrick replaces that with a precise lookup. Ask "where do we deduplicate users by email" and get back a function, file, and line number instead of a 50,000-token rake through source. ## What you can do with it - **Find code by what it does.** Search for "verifies a webhook signature" and get the function back, even when its name says nothing about webhooks. - **Call other services with real types.** Look up an endpoint's actual request and response shapes instead of guessing the JSON. - **Catch contract drift before it ships.** Carrick flags type mismatches, changed routes, wrong HTTP verbs, and dependency-version conflicts between services. ## Connect your agent The MCP endpoint is `https://api.carrick.tools/mcp`. Claude Code, Cursor, Windsurf, and Codex all connect over HTTP. ```bash claude mcp add --transport http carrick https://api.carrick.tools/mcp ``` Sign in once in your browser when prompted, and your agent is connected. Carrick is read-only: every tool call is a query against the index. See [Connecting your agent](/connecting-your-agent) for other clients. ## In CI The Carrick GitHub Action keeps your org's index current on every push, and comments contract-drift findings on your pull requests. See [PR comments](/pr-output). ## Next steps - [Quickstart](/quickstart) sets up Carrick end to end: sign in, add the action, connect your agent, first scan. - [What Carrick covers](/coverage) lists what a repo needs to scan cleanly and what falls outside scope. - [MCP tools](/mcp-tools) is the reference for every tool the server exposes. --- # Quickstart Source: https://docs.carrick.tools/quickstart Updated: 2026-06-01 This guide takes you from zero to a working Carrick install: an indexed repo, an agent talking to the MCP server, and the first PR comment posted automatically. You will need a GitHub account, repo admin access to whichever TypeScript repos you want indexed, and an MCP-aware agent (Claude Code, Cursor, Windsurf, or Codex). ## 1. Sign in with GitHub Go to [app.carrick.tools](https://app.carrick.tools) and click **Sign in with GitHub**. Carrick requests read-only scopes: - `read:user`: your GitHub login and email. - `read:org`: the orgs you belong to, so you can scope your account to one of them on the next screen. - `public_repo`: read access to your public repos. Carrick stores your access token securely and uses it only to read what the scanner needs. ## 2. Pick your scope If your GitHub account belongs to one or more orgs, the next screen asks you to pick where this Carrick account's keys live: your personal namespace, or one of the orgs you belong to. Teammates who pick the same org share scan data and cross-repo discovery; teammates who pick different orgs see different indexes. The scope is locked in for this account. To use Carrick with a different scope later, delete the account and sign in again. Solo accounts (no org memberships) skip this step entirely and land on the dashboard with a personal-namespace key ready. ## 3. Copy your API key The dashboard shows the plaintext API key once, on first login. Copy it now and add it as a repository secret named `CARRICK_API_KEY` on every repo you want scanned: 1. In GitHub, open the repo's **Settings → Secrets and variables → Actions**. 2. Click **New repository secret**. 3. Name: `CARRICK_API_KEY`. Value: paste the key you copied from the dashboard. If you lose the key, return to the dashboard and use **Rotate key**. The current key stops working immediately, so update `CARRICK_API_KEY` on every repo before the next scan runs. ## 4. Add the GitHub Action workflow In each TypeScript repo you want indexed, save the following to `.github/workflows/carrick.yml`: ```yaml name: Carrick on: push: branches: [main] pull_request: branches: [main] jobs: carrick: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: daveymoores/carrick@v1 with: carrick-api-key: ${{ secrets.CARRICK_API_KEY }} ``` This is the default workflow the dashboard generates. It scans on every push to `main` and on every pull request. On main, the action uploads results to the index. On pull requests, the action runs the analysis and exposes a `pr-comment` output without posting it. To turn that output into a PR comment, see [PR comments](/pr-output). If your repo uses environment variables to build outbound URLs (`fetch(`${process.env.USER_SERVICE_URL}/users`)`), also add a [carrick.json](/carrick-json) at the repo root to tell the scanner which env vars name internal services and which name third-party APIs. ## 5. Connect your agent over MCP Pick the snippet for your agent. The first request opens a browser tab on `app.carrick.tools/oauth/authorize`; click **Approve** to grant the agent read-only access to the index. Subsequent calls use the long-lived token the agent received. ### Claude Code ```bash claude mcp add --transport http carrick https://api.carrick.tools/mcp ``` ### Cursor Save to `~/.cursor/mcp.json`: ```json { "mcpServers": { "carrick": { "url": "https://api.carrick.tools/mcp" } } } ``` ### Windsurf Save to `~/.codeium/windsurf/mcp_config.json`: ```json { "mcpServers": { "carrick": { "serverUrl": "https://api.carrick.tools/mcp" } } } ``` ### Codex Save to `~/.codex/config.toml`: ```toml [mcp_servers.carrick] command = "npx" args = ["-y", "mcp-remote", "https://api.carrick.tools/mcp"] ``` For agents that do not support MCP OAuth discovery, you can paste the API key into the connection headers directly. See [Connecting your agent](/connecting-your-agent) for the manual variants and the consent-screen details. ## 6. Your first scan Push to `main` (or open a pull request) on any repo that now has `.github/workflows/carrick.yml`. The action will: 1. Download the Carrick release. 2. Scan the repo's TypeScript source. 3. Upload the results to your org's index (main-branch runs only; pull-request runs skip the upload). After the action finishes, your agent can immediately call MCP tools. Ask it something only Carrick should know: > Use Carrick to list every service in our org and the number of endpoints each one exposes. The agent calls `list_services` and answers in one turn. See [MCP tools](/mcp-tools) for the full set. ## What to set up next - [Connecting your agent](/connecting-your-agent). Add a short Carrick block to your `AGENTS.md` so your agent knows when to reach for Carrick before grepping or reimplementing. - [PR comments](/pr-output). Extend the workflow to post the action's `pr-comment` output on pull requests, updating in place across pushes. - [carrick.json](/carrick-json). Classify env-var-driven outbound calls so contract checking can run against them. --- # What Carrick covers Source: https://docs.carrick.tools/coverage Updated: 2026-06-01 Carrick scans TypeScript REST services. It finds your API endpoints and the calls between services, resolves their request and response types, and indexes the result. Your agent queries that index over MCP, and the GitHub Action surfaces contract drift on pull requests. Before you wire Carrick into a repo, check the requirements below hold and the limitations don't block your use case. Both lists are short on purpose: the supported scope is deliberately narrow. ## Requirements A repo scans cleanly when all of these are true: - **TypeScript source.** Carrick reads request and response types from TypeScript. Pure JavaScript repos can still produce a route map, but endpoint shapes will be `unknown` because there are no types to read. - **A `package.json`.** Used to detect the framework, resolve dependencies, and ground the dependency conflict checks. - **Statically discoverable routes.** Carrick finds routes by reading your source, not by running your code. If a path string or HTTP method is a literal in source (or resolvable to one), it gets indexed. If it is computed at runtime from a config file, a database, or an environment variable, it does not. See "Dynamic routing" below. - **GitHub Actions.** Carrick runs as a GitHub Action, once per push or pull request, and uploads the result on main-branch runs. Local-only scans aren't supported. ## Framework coverage Carrick works across REST frameworks. It matches on call shape (`app.get`, `router.use`, `axios.post`, decorators, common HTTP-client patterns) rather than specific framework packages, and adapts to the framework and version it detects in your `package.json`. Express 4 vs Express 5, Fastify 3 vs Fastify 4: version differences are handled automatically. End-to-end fixture coverage as of today: - **Express** has full producer plus consumer coverage, including response-type extraction and parameter and body-type extraction. - **Koa, Fastify, Hono, NestJS, and Hapi** all have code-present extraction paths and should work in practice. They are not yet covered by end-to-end fixtures, so report a bug if a route does not appear in your index after a clean scan. For unusual or in-house Express-flavoured routers, the scanner generally still picks them up because matching is on imported symbols and call shape rather than framework name. If your framework is detected but routes do not appear in the index, that is a bug worth reporting. If the framework is not detected at all, the dashboard report will say so explicitly. ## What Carrick does not cover These are out of scope at MVP and will stay that way unless we hear consistent demand. ### Non-TypeScript services Python, Go, Rust, Java, Ruby. Carrick relies on TypeScript's compiler to extract type shapes. Porting the type sidecar to other languages is a large undertaking that does not move the needle for the TypeScript-monorepo problem Carrick exists to solve. If your stack is mixed, the TypeScript services will scan and the rest will be invisible. ### Non-REST protocols - **GraphQL.** If the scanner detects a GraphQL client (`graphql-request`, `@apollo/client`, `urql`, and similar), the report includes a banner that says "REST contracts only" and lists the detected libraries. The endpoints those clients call are not indexed. - **gRPC, tRPC over WebSocket, custom RPC frameworks.** These do not produce HTTP route handlers in the shape the scanner looks for, so the routes will not appear in the index even if the consumer and producer are both TypeScript. - **Message queues, event buses, Kafka, RabbitMQ.** Async messaging falls outside the REST contract surface entirely. ### Dynamic routing Carrick reads your source, it does not run your code. The following patterns are invisible to it: - Routes built at runtime from a config file, a database, or environment-driven feature flags. - Routes registered from arrays in a loop where the path strings are computed from variables the scanner cannot resolve to literals. - Routes added by a plugin system where the plugin path is determined after the process starts. The bar is: static enough to read from source. If the path strings and method names are literal in source (or trivially resolvable to literals), Carrick finds them. ### Compiled or generated code - **`.d.ts`-only services without source.** There is nothing to scan. - **Generated routes that live only in `dist/`** at runtime. If the generator commits its output to the repo, the routes scan; if the generator runs at build time and the output is gitignored, they do not. - **Pre-compiled bundles.** The scanner operates on TypeScript source, not on compiled JavaScript bundles or minified output. ### Monorepos without per-service `package.json` Each service Carrick indexes corresponds to one `package.json`. Polyrepos work out of the box. Monorepos with workspaces also work as long as each service directory has its own `package.json` (pnpm workspaces, npm workspaces, Yarn workspaces, Nx with per-app manifests). A monorepo with one root `package.json` covering many service directories cannot be split into separate services by Carrick; the whole repo will be indexed as a single service. ## Related - [Introduction](/introduction). What Carrick is for and what you can do with it. - [carrick.json](/carrick-json). Classify env-var-driven outbound calls so contract checking can run against them. --- # Connecting your agent Source: https://docs.carrick.tools/connecting-your-agent Updated: 2026-06-01 Carrick's MCP endpoint runs at `https://api.carrick.tools/mcp` over HTTP transport. Any MCP-aware agent that supports HTTP servers can connect. This guide covers the four clients with first-class snippets in the dashboard. ## How the connection works The recommended setup signs you in through your browser. The first time your agent calls Carrick, it opens a consent screen. Sign in, click **Approve**, and your agent stays connected across sessions. The consent screen lists what the agent can read once approved: - Function intents - Type definitions - Dependencies and version drift - API endpoints with request and response types - Cross-service contract compatibility All of this is read-only. The agent can't write to the index, change settings, or trigger scans. If your client can't sign in through the browser, paste an API key from the dashboard into its config instead. The "Manual fallback" sections below show how for each client. ## Claude Code ### Discovery (recommended) ```bash claude mcp add --transport http carrick https://api.carrick.tools/mcp ``` Claude opens the consent URL on the first tool call. Approve once, and the token persists across sessions. ### Manual fallback ```bash claude mcp add --transport http carrick https://api.carrick.tools/mcp \ --header "Authorization: Bearer " ``` Use this only if discovery is unavailable, or for a service account. ## Cursor ### Discovery Save to `~/.cursor/mcp.json`: ```json { "mcpServers": { "carrick": { "url": "https://api.carrick.tools/mcp" } } } ``` Restart Cursor. The first tool call opens the consent screen in your browser. ### Manual fallback ```json { "mcpServers": { "carrick": { "url": "https://api.carrick.tools/mcp", "headers": { "Authorization": "Bearer " } } } } ``` ## Windsurf ### Discovery Save to `~/.codeium/windsurf/mcp_config.json`: ```json { "mcpServers": { "carrick": { "serverUrl": "https://api.carrick.tools/mcp" } } } ``` ### Manual fallback ```json { "mcpServers": { "carrick": { "serverUrl": "https://api.carrick.tools/mcp", "headers": { "Authorization": "Bearer " } } } } ``` ## Codex Codex talks to MCP servers through `mcp-remote`, which terminates HTTP transport locally. ### Discovery Save to `~/.codex/config.toml`: ```toml [mcp_servers.carrick] command = "npx" args = ["-y", "mcp-remote", "https://api.carrick.tools/mcp"] ``` ### Manual fallback ```toml [mcp_servers.carrick] command = "npx" args = [ "-y", "mcp-remote", "https://api.carrick.tools/mcp", "--header", "Authorization: Bearer ", ] ``` ## Tell your agent when to use Carrick Connecting the server makes the tools available, but your agent won't reach for them unless it knows to. Carrick's MCP server ships a default set of usage rules, and clients that read them (Claude Code, Cursor) pick them up automatically, so often you don't need to do anything. To make the rules explicit, or add your own, paste this into your repo's `AGENTS.md` (or `CLAUDE.md` / `.cursor/rules/`, whichever your agent reads): ```md ## Carrick Carrick indexes every TypeScript service in this org. When working in TypeScript, use it before grepping or reimplementing: - Before writing a helper, parser, validator, or formatter: `search_by_intent` to find an existing one ("dedupe users by email", "verify a webhook signature"). - Before calling another service: `get_api_endpoints`, then `get_endpoint_types` instead of guessing the JSON. - Before changing a route, a response shape, or an HTTP verb: `check_compatibility` against each consumer. - Before adding or bumping an npm dependency: `get_service_dependencies`. Carrick is read-only; data reflects each repo's last scan. ``` ## Other MCP clients If your client supports HTTP-transport MCP servers, point it at `https://api.carrick.tools/mcp`. If the client does not support OAuth discovery, add an `Authorization: Bearer ` header to the request. If your client only supports stdio transport, run [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) as a shim, the same way the Codex config above does. ## Rotating the API key If you need to revoke a token (lost laptop, suspected leak, scheduled rotation), open the dashboard at [app.carrick.tools](https://app.carrick.tools) and click **Rotate key**. The previous key stops working immediately. Update every place the key is configured: - `CARRICK_API_KEY` in GitHub Actions secrets on every indexed repo. - The `Authorization` header on any agent using the manual fallback. Tokens from the browser sign-in flow keep working after a rotation. Rotating the API key only affects clients using the manual fallback. ## Related - [Quickstart](/quickstart) covers the end-to-end signup and first scan. - [MCP tools](/mcp-tools) is the reference for what the agent can call. --- # carrick.json Source: https://docs.carrick.tools/carrick-json Updated: 2026-06-01 `carrick.json` is a small JSON file you check in at the root of each indexed repo. It tells the Rust scanner how to classify outbound HTTP calls that were built from environment variables or URL prefixes. Without it, calls like `fetch(`${process.env.USER_SERVICE_URL}/users`)` cannot be resolved at scan time, and contract checking has nothing to compare them against. This is different from your agent instruction file (`AGENTS.md` or `CLAUDE.md`). That file tells your coding agent when to call Carrick; `carrick.json` tells the scanner how to classify outbound calls. See [Connecting your agent](/connecting-your-agent) for the agent side. ## Why it exists When the scanner sees a call expression like `fetch(process.env.ORDER_SERVICE_URL + '/orders')`, it has the HTTP method, but not the destination. The env var might point at another service in your org (in which case Carrick should validate the call against the index) or at a third-party API like Stripe or GitHub (in which case Carrick should ignore the call entirely). Carrick can't guess which is which, so you declare it once per env var. When you have not classified an env var, the action surfaces it as a warning in the PR comment: > Unclassified env var: POST /orders using [ORDER_SERVICE_URL] (from src/orders.ts) — add to `internalEnvVars` or `externalEnvVars` in carrick.json Resolve the warning by adding the env var to the appropriate list and committing the file. ## Schema ```json { "serviceName": "order-service", "internalEnvVars": ["USER_SERVICE_URL", "INVENTORY_API"], "externalEnvVars": ["STRIPE_API", "GITHUB_API"], "internalDomains": ["https://api.yourcompany.com"], "externalDomains": ["https://api.stripe.com", "https://api.github.com"] } ``` | Field | Type | Purpose | | :--- | :--- | :--- | | `serviceName` | string | Friendly name for this service, used in MCP responses and the dashboard. Defaults to the repo name if omitted. | | `internalEnvVars` | string array | Env var names whose values point at other services in your org. Calls built from these are matched against the index. | | `externalEnvVars` | string array | Env var names whose values point at third-party APIs. Calls built from these are ignored by contract checking. | | `internalDomains` | string array | Full URL prefixes for internal services. Calls whose target URL starts with one of these are matched against the index. | | `externalDomains` | string array | Full URL prefixes for third-party APIs. Calls whose target URL starts with one of these are ignored. | All fields are optional. An empty `carrick.json` is valid but does nothing; the unclassified-env-var report will fire on every run until you populate at least one list. ## Env vars vs. domains Both env-var matching and domain matching work. Pick whichever fits how your code constructs URLs: - **Env vars** catch indirect patterns: `fetch(`${process.env.USER_SERVICE_URL}/users/${id}`)`. You declare the env-var name, and the scanner classifies every call that uses it regardless of how the path is composed. - **Domains** catch URL literals: `fetch('https://api.stripe.com/v1/charges')`. You declare a prefix, and the scanner classifies any call whose target URL starts with that prefix. Most production codebases lean on env vars for internal services and inline literals or SDKs for third-party APIs, so the typical mix is `internalEnvVars` for your own services and `externalDomains` for the third parties. ## A monorepo with multiple services If your repo holds more than one service (each with its own `package.json`), you can place a `carrick.json` next to each service's `package.json`. Carrick finds every `carrick.json` in the repo and merges them: all the `internalEnvVars` together, all the domains together, and so on. The first non-empty `serviceName` wins. For a polyrepo where each service is its own GitHub repo, the simpler pattern is one `carrick.json` at the repo root. ## Example: a service with mixed dependencies ```json { "serviceName": "checkout", "internalEnvVars": [ "ORDER_SERVICE_URL", "INVENTORY_SERVICE_URL", "USER_SERVICE_URL" ], "externalEnvVars": [ "STRIPE_API_BASE" ], "externalDomains": [ "https://api.sendgrid.com", "https://hooks.slack.com" ] } ``` The checkout service in this example talks to three internal services (declared by env var), to Stripe (declared by env var because the base URL is configured per environment), and to SendGrid and Slack (declared by domain because the URLs are literal in source). ## Related - [Quickstart](/quickstart). Where carrick.json fits into the initial setup. - [PR comments](/pr-output). Where the unclassified-env-var warning appears. --- # PR comments Source: https://docs.carrick.tools/pr-output Updated: 2026-06-01 Carrick can post a findings comment on your pull requests: type mismatches between services, changed or missing routes, wrong HTTP verbs, and dependency-version conflicts. The comment is posted by the Carrick GitHub App and updated in place on each push, so a PR never collects a stack of duplicates. ## Turn it on PR comments are off by default and set per project. 1. Install the GitHub App on the repos you want, from the project's **Repos** page. 2. Open the project in the dashboard at [app.carrick.tools](https://app.carrick.tools). 3. Under **PR comments**, click **Enable**. That is the whole setup. There is no workflow step to add and no token to manage: the App authenticates itself and posts the comment for you. ## What gets posted On each pull request, Carrick compares the branch against the project's index and comments when it finds contract drift: - A consumer calls an endpoint the producer no longer exposes, or with a mismatched method or path. - A request or response type no longer lines up between a producer and its consumers. - A dependency is pinned to a version that conflicts with the rest of the project. When there is nothing to flag, Carrick does not comment. The single comment is rewritten in place as the PR evolves, so the latest state is always there rather than buried under older runs. ## Turn it off Toggle **PR comments** off on the project page at any time. Existing comments stay; no new ones are posted. ## Related - [Quickstart](/quickstart) covers installing the App and connecting repos. - [carrick.json](/carrick-json) classifies the outbound calls that contract checking runs against. --- # MCP tools Source: https://docs.carrick.tools/mcp-tools Updated: 2026-06-01 The Carrick MCP server exposes your indexed services as structured tools and resources. The endpoint is `https://api.carrick.tools/mcp`, or `https://api.carrick.tools/mcp/p/` for a specific project. Your token is scoped to one project, and every tool returns data for that project only. Tools are listed below in the order they typically fire during a coding session. ## Intent layer ### `search_by_intent(query, top_k?, similarity_threshold?)` Semantic search across every exported function in the org, ranked by how closely each matches your query. Reach for it when the agent is asking a concept question ("verify a webhook signature", "dedupe users by email") where keywords do not help. It searches the whole org, not a sampled subset. **Parameters:** | Name | Type | Required | Default | Notes | | :--- | :--- | :--- | :--- | :--- | | `query` | string | yes | | Plain-English description of what the function should do. | | `top_k` | number | no | 8 | How many matches to return. | | `similarity_threshold` | number | no | 0.3 | Score floor for inclusion. Raise to filter weak matches; lower to widen results. | **Response shape:** ```json { "query": "verify a webhook signature", "top_k": 8, "similarity_threshold": 0.3, "total_embedded_scanned": 1247, "total_above_threshold": 4, "results": [ { "service": "billing", "repo": "billing-service", "name": "verifyStripeWebhook", "file_path": "src/webhooks/stripe.ts", "line_number": 24, "intent": "Verifies a Stripe webhook signature using the signing secret and rejects requests with mismatched HMACs.", "similarity": 0.82 } ] } ``` ### `list_function_intents(service?, exclude_service?)` Returns the full haystack of every exported function in the org alongside its LLM-generated intent. Useful for browsing a service's surface area, or for comparing what sibling services have implemented. Prefer `search_by_intent` for concept queries. Use this when you want to scan a whole service end to end, or to diff implementations across two services. **Parameters:** | Name | Type | Required | Notes | | :--- | :--- | :--- | :--- | | `service` | string | no | Restrict to one service. | | `exclude_service` | string | no | Restrict to everything except one service. | **Response shape:** ```json { "total": 1247, "services": ["billing", "checkout", "inventory"], "functions": [ { "service": "billing", "repo": "billing-service", "name": "verifyStripeWebhook", "file_path": "src/webhooks/stripe.ts", "line_number": 24, "intent": "Verifies a Stripe webhook signature using the signing secret and rejects requests with mismatched HMACs." } ] } ``` ## Structural and type layer ### `list_services()` Catalogue of every service in the org's index. Cheap. Call this first when orienting. **Response shape:** ```json [ { "repo_name": "billing-service", "service_name": "billing", "endpoint_count": 14, "call_count": 9, "last_updated": "2026-05-24T19:02:11Z", "commit_hash": "a3f1c9d", "has_types": true } ] ``` ### `get_api_endpoints(service, method?, path_contains?)` Endpoints a service exposes. Returns one row per endpoint with HTTP method, fully-resolved path (mount-aware), handler reference, mount owner, and the source file location. Reach for it before writing client code that calls a service, or before changing one of its routes. **Parameters:** | Name | Type | Required | Notes | | :--- | :--- | :--- | :--- | | `service` | string | yes | The service to inspect. | | `method` | string | no | Filter to one HTTP method (`GET`, `POST`, ...). | | `path_contains` | string | no | Substring filter on path. | **Response shape:** ```json { "service": "billing", "endpoint_count": 1, "endpoints": [ { "method": "POST", "full_path": "/api/v1/invoices", "handler": "createInvoice", "owner": "billingRouter", "file_location": "src/routes/invoices.ts:42" } ] } ``` ### `get_endpoint_types(service, method, path)` Resolved TypeScript request and response types for a single endpoint. Each entry tells you whether the type was explicitly annotated or inferred from the handler body, and includes the source location. Reach for it before building a request body or parsing a response. Guessing JSON shapes from a sample is the most common source of contract drift. **Parameters:** | Name | Type | Required | Notes | | :--- | :--- | :--- | :--- | | `service` | string | yes | The service exposing the endpoint. | | `method` | string | yes | HTTP method. | | `path` | string | yes | Path, matched against the service's mount graph. | **Response shape:** ```json { "service": "billing", "method": "POST", "path": "/api/v1/invoices", "types": [ { "type_alias": "CreateInvoiceRequest", "type_kind": "request_body", "is_explicit": true, "source_file": "src/types/invoices.ts", "source_line": 12, "definition": "{ customer_id: string; amount_cents: number; currency: string }" }, { "type_alias": "Invoice", "type_kind": "response_body", "is_explicit": false, "source_file": "src/routes/invoices.ts", "source_line": 58, "definition": "{ id: string; status: 'open' | 'paid'; amount_cents: number }" } ] } ``` ### `get_type_definition(service, type_alias)` Fully resolved definition for one named type, with transitive dependencies expanded. Use it when `get_endpoint_types` references a named DTO, discriminated union, or composed type whose shape you need to read. **Parameters:** | Name | Type | Required | | :--- | :--- | :--- | | `service` | string | yes | | `type_alias` | string | yes | **Response shape:** ```json { "service": "billing", "type_alias": "Invoice", "definition": "{ id: string; status: InvoiceStatus; amount_cents: number; line_items: LineItem[] }", "expanded": "{ id: string; status: 'open' | 'paid' | 'void'; amount_cents: number; line_items: { sku: string; quantity: number; unit_price_cents: number }[] }" } ``` ### `check_compatibility(consumer_service, producer_service, method?, path?)` Diff a consumer's outbound calls against a producer's exposed endpoints. Surfaces missing endpoints (the consumer calls something the producer no longer exposes) and unused endpoints (the producer exposes routes that nobody calls). Reach for it before removing a route, renaming a path, or changing a producer's response shape. **Parameters:** | Name | Type | Required | Notes | | :--- | :--- | :--- | :--- | | `consumer_service` | string | yes | The service making the calls. | | `producer_service` | string | yes | The service exposing the endpoints. | | `method` | string | no | Limit to one HTTP method. | | `path` | string | no | Limit to calls matching a path. | **Response shape:** ```json { "consumer": "checkout", "producer": "billing", "compatible": false, "consumer_calls": 6, "producer_endpoints": 14, "issues": [ { "severity": "error", "category": "missing_endpoint", "message": "Consumer calls POST /api/v1/invoices/draft but producer has no matching endpoint" }, { "severity": "info", "category": "unused_endpoint", "message": "Producer exposes DELETE /api/v1/invoices/:id but consumer doesn't call it" } ] } ``` ### `get_service_dependencies(service?)` With no argument, returns org-wide npm dependency conflicts: any package pinned to more than one version across services. With a service name, returns that service's merged dependency map. Reach for it before adding or upgrading an npm dependency, or when a TypeScript build error looks like a version mismatch. **Parameters:** | Name | Type | Required | Notes | | :--- | :--- | :--- | :--- | | `service` | string | no | Omit for org-wide conflict view. | **Org-wide response shape:** ```json { "total_packages": 312, "conflict_count": 4, "conflicts": [ { "package_name": "zod", "severity": "error", "versions": [ { "service": "billing", "version": "3.22.4" }, { "service": "checkout", "version": "4.0.1" } ] } ] } ``` **Per-service response shape:** ```json { "service": "billing", "package_count": 87, "dependencies": { "zod": { "version": "3.22.4" } } } ``` ## Onboarding ### `scaffold()` Generates the files needed to onboard the current repo onto Carrick: the GitHub Actions workflow (`.github/workflows/carrick.yml`, keyless via OIDC), a `carrick.md` instruction block, and a `carrick.json` config skeleton. It returns the files plus instructions telling the agent to write each one and to fill in `carrick.json` by scanning the repo for its service name and the env vars and domains it calls. Your coding agent calls this once per repo during setup. Takes no parameters. ## Resources Resources are read-only URIs that the MCP client can fetch directly. ### `carrick://services` Full service catalogue as JSON. Equivalent to `list_services()` but exposed as a resource so the client can subscribe to it. ### `carrick://services/{name}/types.d.ts` Bundled `.d.ts` file for one service. Useful when you want the agent to read the whole type surface area in one fetch instead of round-tripping `get_type_definition` for each name. ## Errors and empty results Every tool returns a single `text` content block containing JSON. Errors and empty results are represented as plain text inside the same block: - Missing service: `Service "checkout" not found. Use list_services to see available services.` - Empty search: `Scanned 1247 embedded intents but none scored above the similarity threshold of 0.3. Try a more concrete phrase, or relax similarity_threshold.` - Missing types: `Endpoint POST /api/v1/invoices exists but has no extracted types.` Treat any response whose first character is not `{` or `[` as a textual diagnostic rather than a structured payload. ## Related - [Connecting your agent](/connecting-your-agent) covers the setup that gates access to these tools, and the instruction block that tells your agent when to reach for each. - [Quickstart](/quickstart) walks the full setup end to end.