MCP tools
Reference for every tool and resource the Carrick MCP server exposes at api.carrick.tools/mcp.
The Carrick MCP server exposes your indexed services as structured tools and resources. The endpoint is https://api.carrick.tools/mcp — one URL for everything. Your token is scoped to a workspace, and each tool call resolves to exactly one project inside it.
Tools are listed below in the order they typically fire during a coding session.
Project scoping
A workspace can hold several projects (one project = one interconnected system of repos). Every data tool accepts two optional arguments that pick which project a call queries:
| Name | Type | Notes |
|---|---|---|
project | string | Carrick project slug to query. |
repo | string | Your repo as owner/repo (from the git remote) or just the repo name. Carrick resolves which project it belongs to. |
Pass one of them on every call — a repo’s carrick.md usually pins the right project slug. When the workspace has a single project, both can be omitted. If a call can’t be resolved to exactly one project, the tool returns a short teaching message telling the agent what to pass; list_projects shows the options.
These two parameters are not repeated in the tables below.
Intent layer
search_by_intent(query, top_k?, similarity_threshold?)
Semantic search across every exported function in the project, 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 project, 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 (max 50). |
similarity_threshold | number | no | 0.3 | Score floor for inclusion. Raise to filter weak matches; lower to widen results. |
Response shape:
{
"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?, limit?, offset?, typed_only?, name_contains?, intent_contains?)
Lists exported functions alongside their LLM-generated intents. 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. Results are paginated: the full haystack runs to thousands of functions, so each call returns one page and a next_offset to fetch the next.
Parameters:
| Name | Type | Required | Default | Notes |
|---|---|---|---|---|
service | string | no | Restrict to one service. | |
exclude_service | string | no | Restrict to everything except one service. | |
limit | number | no | 50 | Max functions per page (max 200). |
offset | number | no | 0 | Functions to skip before this page. Pass a previous response’s next_offset to page through. |
typed_only | boolean | no | false | Only functions whose signature is fully explicit (every param and the return annotated). |
name_contains | string | no | Case-insensitive substring filter on the function name. | |
intent_contains | string | no | Case-insensitive substring filter on the intent text. |
Response shape:
{
"total": 1247,
"returned": 50,
"offset": 0,
"limit": 50,
"has_more": true,
"next_offset": 50,
"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.",
"typed": true,
"reason": ""
}
]
}
total counts the filtered set before pagination. typed is true when every parameter and the return are explicitly annotated; otherwise reason names the inferred positions (e.g. param `role` and return are inferred). Fully scanned signatures also carry signature and a per-position types_explicit map.
Structural and type layer
list_projects()
Lists the projects in your workspace and each project’s connected repos. Call it when you don’t know which project slug or repo name to pass to the other tools. Cheap — it reads workspace metadata only, no scan data. Takes no parameters (not even project/repo).
Response shape:
{
"projects": [
{
"slug": "storefront",
"display_name": "Storefront",
"repos": ["acme/billing-service", "acme/checkout"]
}
],
"usage": "Pass `project: \"<slug>\"` (or `repo: \"<owner/repo>\"`) on the other Carrick tools to query that system."
}
list_services()
Catalogue of every service in the project’s index. Cheap. Call this first when orienting.
Response shape:
[
{
"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
}
]
endpoint_count and call_count count operations across every protocol, the same way get_api_endpoints lists them.
get_api_endpoints(service, method?, path_contains?)
The operations a service exposes, across protocols: HTTP endpoints (GET /api/users/:id), GraphQL fields (query user), and socket events (chat:message (client→server)). Returns one row per operation; HTTP rows are mount-aware, with fully-resolved paths.
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 (fuzzy match by repo name, service name, or trailing segment). |
method | string | no | Filter by operation label: HTTP method (GET, POST, …), GraphQL kind (QUERY, MUTATION, SUBSCRIPTION), or socket direction (CLIENT->SERVER, SERVER->CLIENT). |
path_contains | string | no | Substring filter on the path, GraphQL field, or event name. |
Response shape:
{
"service": "billing",
"endpoint_count": 1,
"endpoints": [
{
"protocol": "http",
"operation": "POST /api/v1/invoices",
"method": "POST",
"full_path": "/api/v1/invoices",
"handler": "createInvoice",
"owner": "billingRouter",
"file_location": "src/routes/invoices.ts:42"
}
]
}
For GraphQL and socket rows, method/full_path carry the operation’s label pair instead — (QUERY, user) or (CLIENT->SERVER, chat:message).
get_endpoint_types(service, method, path)
Resolved TypeScript request and response types for a single operation. 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 — or, for a non-HTTP operation, its label from get_api_endpoints (QUERY, MUTATION, CLIENT->SERVER). |
path | string | yes | API path (matched against the service’s mount graph), GraphQL field, or socket event name. |
Response shape:
{
"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:
{
"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 operations. HTTP calls get method-and-path matching; GraphQL and socket operations get exact-key existence checks. Surfaces missing operations (the consumer uses something the producer doesn’t expose) and unused ones (the producer exposes operations nobody calls).
Reach for it before removing a route, renaming a path, field, or event, 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 operations. |
method | string | no | Filter by operation label: HTTP method, GraphQL kind, or socket direction. |
path | string | no | Filter by HTTP path, GraphQL field, or socket event name. |
Response shape:
{
"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 project-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 the project-wide conflict view. |
Project-wide response shape:
{
"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:
{
"service": "billing",
"package_count": 87,
"dependencies": {
"zod": { "version": "3.22.4" }
}
}
Onboarding
scaffold()
Generates the files needed to onboard the current repo onto Carrick, and returns them with instructions for the agent to act on:
.github/workflows/carrick.yml— the scan workflow, written verbatim. Keyless via GitHub Actions OIDC; there is no secret to configure.carrick.md— an instruction block telling the agent when to reach for Carrick’s tools, pinned to the resolved project slug. The instructions say to fold it into an existingAGENTS.md/CLAUDE.mdwhen the repo has one.carrick.json— a config skeleton the agent is told to populate by scanning the repo: the service name(s), and the env vars and domains that name internal services versus third-party APIs (using aservicesarray for monorepos).
Your coding agent calls this once per repo during setup. Takes only the shared project/repo scoping arguments, and — unlike the data tools — works on a project whose repos have never been scanned, since that’s exactly when you run it.
Resources
Resources are read-only URIs that the MCP client can fetch directly. Resource URIs carry no project/repo arguments, so they resolve from the token alone: they work when the workspace has a single project, and return a teaching message otherwise.
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. - Unresolved project: a short message telling the agent to pass
projectorrepo(and which slugs exist). - Project with no scan data yet: a message saying the project resolved but its repos haven’t been scanned since being connected.
- 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 covers the setup that gates access to these tools, and the instruction block that tells your agent when to reach for each.
- Quickstart walks the full setup end to end.