@usethrottle/mcp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lib.d.ts ADDED
@@ -0,0 +1,165 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { ActionDefinition } from '@core/action-catalog';
3
+
4
+ interface AuthCtx {
5
+ apiKey: string;
6
+ apiBaseUrl: string;
7
+ }
8
+ interface RequestOptions {
9
+ body?: unknown;
10
+ query?: Record<string, unknown>;
11
+ /**
12
+ * Sent as `Idempotency-Key`. Writes must pass one: an agent that retries is the
13
+ * normal case, and the API dedupes on
14
+ * `(workspace, application, environment, key, method, path)`.
15
+ */
16
+ idempotencyKey?: string;
17
+ }
18
+ interface Pagination {
19
+ cursor: string | null;
20
+ hasMore: boolean;
21
+ }
22
+ interface ListResult<T> {
23
+ data: T[];
24
+ pagination: Pagination | null;
25
+ }
26
+ type Fetcher = typeof fetch;
27
+ declare class ThrottleClient {
28
+ private readonly auth;
29
+ private readonly fetchImpl;
30
+ constructor(auth: AuthCtx, fetchImpl?: Fetcher);
31
+ private requestJson;
32
+ /** Unwraps the `{ data }` envelope. Key presence, not `??` — `{data: null}` unwraps to null. */
33
+ get<T>(path: string, query?: Record<string, unknown>): Promise<T>;
34
+ list<T>(path: string, query?: Record<string, unknown>): Promise<ListResult<T>>;
35
+ post<T>(path: string, options?: RequestOptions): Promise<T>;
36
+ }
37
+
38
+ /**
39
+ * `describe_endpoint` and `validate_payload`, answered from the OpenAPI contract
40
+ * bundled at build time. No network, no API quota.
41
+ *
42
+ * Why this exists: Throttle's public API is strict camelCase and rejects the
43
+ * retired snake_case aliases — and those aliases are exactly what a model writing
44
+ * commerce code will guess, because that is what the rest of the internet's
45
+ * examples look like. Naming the replacement turns a 400-debug loop into one call.
46
+ */
47
+ interface ContractField {
48
+ name: string;
49
+ type?: string;
50
+ required: boolean;
51
+ description?: string;
52
+ enum?: string[];
53
+ }
54
+ interface ContractOperation {
55
+ method: string;
56
+ /** OpenAPI-style path, e.g. `/api/v1/customers/{customerId}/addresses/{id}`. */
57
+ path: string;
58
+ summary?: string;
59
+ description?: string;
60
+ pathParams: string[];
61
+ queryParams: ContractField[];
62
+ bodyFields: ContractField[] | null;
63
+ }
64
+ interface ContractIndex {
65
+ generatedAt: string;
66
+ operations: ContractOperation[];
67
+ }
68
+
69
+ /**
70
+ * `search_docs`, answered from an index of `apps/docs` bundled at build time.
71
+ *
72
+ * Scoring mirrors the CLI's proven approach: title hits beat heading hits, which
73
+ * beat body hits, and an exact phrase beats scattered terms. Deliberately simple —
74
+ * the agent gets a title, a canonical docs.usethrottle.dev URL and an excerpt, then
75
+ * fetches the page itself if its client can.
76
+ */
77
+ interface DocsEntry {
78
+ title: string;
79
+ route: string;
80
+ headings: string[];
81
+ text: string;
82
+ }
83
+ interface DocsIndex {
84
+ generatedAt: string;
85
+ entries: DocsEntry[];
86
+ }
87
+
88
+ interface Identity {
89
+ type: string;
90
+ scopes: string[];
91
+ workspace: {
92
+ id: string;
93
+ name: string | null;
94
+ slug: string | null;
95
+ } | null;
96
+ application: {
97
+ id: string;
98
+ name: string | null;
99
+ slug: string | null;
100
+ } | null;
101
+ environment: {
102
+ id: string;
103
+ slug: string;
104
+ kind: string;
105
+ providerEnvironment: 'sandbox' | 'production';
106
+ };
107
+ apiKey: {
108
+ id: string;
109
+ name: string;
110
+ keyPrefix: string;
111
+ } | null;
112
+ }
113
+ interface HandlerContext {
114
+ client: ThrottleClient;
115
+ identity: Identity;
116
+ contract: ContractIndex;
117
+ docs: DocsIndex;
118
+ }
119
+
120
+ declare const VERSION: string;
121
+ interface RegistrationPolicy {
122
+ identity: Identity;
123
+ allowWrites: boolean;
124
+ allowLiveWrites: boolean;
125
+ }
126
+ /**
127
+ * Which tools this session gets. Pure and exported so the policy is testable
128
+ * without standing up a transport.
129
+ *
130
+ * Four independent gates, in order of how expensive it is to get them wrong:
131
+ *
132
+ * 1. **Implemented.** `0.1.0` ships the read/sandbox half; the catalog describes
133
+ * the money writes before this package implements them.
134
+ * 2. **Scope.** Delegated to the catalog's `canRunAction`, which uses the API's own
135
+ * `hasScope`. A tool the credential cannot execute is not registered at all,
136
+ * rather than failing at call time — the model never sees an affordance it
137
+ * cannot use.
138
+ * 3. **Intent.** Holding a write scope means the credential *may* write; it does
139
+ * not mean the operator intended this session to. That is `--allow-writes`.
140
+ * 4. **Blast radius.** Against a production credential, writes need
141
+ * `--allow-live-writes` on top. Sandbox-only actions invert the rule: they are
142
+ * free in a non-production environment and forbidden in production regardless
143
+ * of flags.
144
+ */
145
+ declare function registerableActions(policy: RegistrationPolicy): ActionDefinition[];
146
+ /**
147
+ * The server's `instructions`, which most clients put in front of the model before
148
+ * it picks a tool. Leads with the environment because the single most damaging
149
+ * mistake an agent can make here is not knowing whether it is looking at live data.
150
+ */
151
+ declare function buildInstructions(identity: Identity, actions: ActionDefinition[], policy: {
152
+ allowWrites: boolean;
153
+ allowLiveWrites: boolean;
154
+ }): string;
155
+ interface CreateServerOptions extends RegistrationPolicy {
156
+ client: ThrottleClient;
157
+ contract: ContractIndex;
158
+ docs: DocsIndex;
159
+ }
160
+ declare function createServer(options: CreateServerOptions): McpServer;
161
+
162
+ declare function loadDocsIndex(): DocsIndex;
163
+ declare function loadContractIndex(): ContractIndex;
164
+
165
+ export { type ContractIndex, type CreateServerOptions, type DocsIndex, type HandlerContext, type Identity, type RegistrationPolicy, ThrottleClient, VERSION, buildInstructions, createServer, loadContractIndex, loadDocsIndex, registerableActions };