@agentvalet/mcp-server 1.6.1 → 1.8.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/README.md CHANGED
@@ -1,70 +1,73 @@
1
- # @agentvalet/mcp-server
2
-
3
- MCP server that lets AI agents (Claude Code, Cursor, Codex CLI, etc.) call approved external platforms through the AgentValet proxy.
4
-
5
- ## Quick start
6
-
7
- ```bash
8
- npx @agentvalet/register # registers this machine as an agent, writes config
9
- ```
10
-
11
- The CLI writes env vars and optionally updates `.mcp.json` or `.cursor/mcp.json` automatically.
12
-
13
- ## Manual configuration
14
-
15
- Add to your `.mcp.json` or equivalent:
16
-
17
- ```json
18
- {
19
- "mcpServers": {
20
- "agentvalet": {
21
- "command": "npx",
22
- "args": ["-y", "@agentvalet/mcp-server"],
23
- "env": {
24
- "AGENT_ID": "agt_...",
25
- "OWNER_ID": "...",
26
- "PROXY_URL": "https://api.agentvalet.ai",
27
- "AGENT_PRIVATE_KEY_PATH": "/path/to/agent.key"
28
- }
29
- }
30
- }
31
- }
32
- ```
33
-
34
- ## Environment variables
35
-
36
- | Variable | Required | Description |
37
- |----------|----------|-------------|
38
- | `AGENT_ID` | Yes | Agent ID from registration |
39
- | `OWNER_ID` | Yes | Owner ID from registration |
40
- | `PROXY_URL` | Yes | AgentValet proxy URL |
41
- | `AGENT_PRIVATE_KEY_PATH` | One of three | Path to PEM private key file |
42
- | `AGENT_PRIVATE_KEY` | One of three | Raw PEM or `\n`-escaped single-line PEM |
43
- | `AGENT_PRIVATE_KEY_B64` | One of three | Base64-encoded PEM |
44
- | `MCP_TRANSPORT` | No | Set to `http` to use HTTP transport instead of STDIO |
45
- | `MCP_PORT` | No | Port for HTTP transport (default: `3100`) |
46
-
47
- ## Tools
48
-
49
- | Tool | Auth | Description |
50
- |------|------|-------------|
51
- | `list_platforms` | JWT | List platforms and scopes this agent has access to |
52
- | `use_platform` | JWT | Call an external platform API through the proxy (blocks for owner approval when required) |
53
- | `authzen_evaluate` | JWT | Pre-check whether this agent has access to a platform scope, without making the call |
54
- | `list_my_pending_actions` | JWT | List this agent's pending approvals and actions completed in the last 24h |
55
- | `request_platform_access` | JWT | Ask an org admin to grant access to a platform the agent is blocked from |
56
- | `report_self_diagnostic` | JWT | Lodge a self-report (error/warning/info) with the owner |
57
- | `agent_register` | None | Self-register a new agent with an owner |
58
- | `agent_status` | None | Poll registration approval status |
59
-
60
- ## Transports
61
-
62
- **STDIO (default)** — compatible with all MCP hosts (Claude Code, Cursor, Codex CLI).
63
-
64
- **HTTP** — set `MCP_TRANSPORT=http` and optionally `MCP_PORT=3100`. Uses `StreamableHTTPServerTransport`.
65
-
66
- ## Architecture
67
-
68
- Each tool call signs a short-lived RS256 JWT (`exp: 60s`) using the agent's private key. The JWT is verified by the AgentValet proxy, which checks permissions and forwards the request to the target platform using stored credentials.
69
-
70
- The agent never sees platform credentials. The proxy decrypts them in-memory at call time and discards them after the upstream request completes.
1
+ # @agentvalet/mcp-server
2
+
3
+ MCP server that lets AI agents (Claude Code, Cursor, Codex CLI, etc.) call approved external platforms through the AgentValet proxy.
4
+
5
+ ## Quick start
6
+
7
+ ```bash
8
+ npx @agentvalet/register # registers this machine as an agent, writes config
9
+ ```
10
+
11
+ The CLI writes env vars and optionally updates `.mcp.json` or `.cursor/mcp.json` automatically.
12
+
13
+ ## Manual configuration
14
+
15
+ Add to your `.mcp.json` or equivalent:
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "agentvalet": {
21
+ "command": "npx",
22
+ "args": ["-y", "@agentvalet/mcp-server"],
23
+ "env": {
24
+ "AGENT_ID": "agt_...",
25
+ "OWNER_ID": "...",
26
+ "PROXY_URL": "https://api.agentvalet.ai",
27
+ "AGENT_PRIVATE_KEY_PATH": "/path/to/agent.key"
28
+ }
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ ## Environment variables
35
+
36
+ | Variable | Required | Description |
37
+ |----------|----------|-------------|
38
+ | `AGENT_ID` | Yes | Agent ID from registration |
39
+ | `OWNER_ID` | Yes | Owner ID from registration |
40
+ | `PROXY_URL` | Yes | AgentValet proxy URL |
41
+ | `AGENT_PRIVATE_KEY_PATH` | One of three | Path to PEM private key file |
42
+ | `AGENT_PRIVATE_KEY` | One of three | Raw PEM or `\n`-escaped single-line PEM |
43
+ | `AGENT_PRIVATE_KEY_B64` | One of three | Base64-encoded PEM |
44
+ | `MCP_TRANSPORT` | No | Set to `http` to use HTTP transport instead of STDIO |
45
+ | `MCP_PORT` | No | Port for HTTP transport (default: `3100`) |
46
+
47
+ ## Tools
48
+
49
+ | Tool | Auth | Description |
50
+ |------|------|-------------|
51
+ | `list_platforms` | JWT | List platforms and scopes this agent has access to |
52
+ | `read_platform` | JWT | Read from an external platform API through the proxy (always GET) |
53
+ | `write_platform` | JWT | Create or update through the proxy (POST/PUT/PATCH; blocks for owner approval when required) |
54
+ | `delete_platform` | JWT | Delete through the proxy (always DELETE; blocks for owner approval when required) |
55
+ | `use_platform` | JWT | Deprecated catch-all. Use the three tools above; removed in the next major. |
56
+ | `authzen_evaluate` | JWT | Pre-check whether this agent has access to a platform scope, without making the call |
57
+ | `list_my_pending_actions` | JWT | List this agent's pending approvals and actions completed in the last 24h |
58
+ | `request_platform_access` | JWT | Ask an org admin to grant access to a platform the agent is blocked from |
59
+ | `report_self_diagnostic` | JWT | Lodge a self-report (error/warning/info) with the owner |
60
+ | `agent_register` | None | Self-register a new agent with an owner |
61
+ | `agent_status` | None | Poll registration approval status |
62
+
63
+ ## Transports
64
+
65
+ **STDIO (default)** — compatible with all MCP hosts (Claude Code, Cursor, Codex CLI).
66
+
67
+ **HTTP** — set `MCP_TRANSPORT=http` and optionally `MCP_PORT=3100`. Uses `StreamableHTTPServerTransport`.
68
+
69
+ ## Architecture
70
+
71
+ Each tool call signs a short-lived RS256 JWT (`exp: 60s`) using the agent's private key. The JWT is verified by the AgentValet proxy, which checks permissions and forwards the request to the target platform using stored credentials.
72
+
73
+ The agent never sees platform credentials. The proxy decrypts them in-memory at call time and discards them after the upstream request completes.
package/dist/index.js CHANGED
@@ -102,7 +102,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
102
102
  ...tool,
103
103
  description: `${tool.description}\nCurrent permissions version: ${version}. If you are holding a ` +
104
104
  `list_platforms result from a different version, it is STALE — call list_platforms ` +
105
- `again before relying on its scopes or requireApproval flags.`,
105
+ `again before relying on its scopes, requireApproval flags, or approvalScopes ` +
106
+ `(the scopes whose calls need human approval under the owner's policy).`,
106
107
  }
107
108
  : tool),
108
109
  };
@@ -146,6 +147,39 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
146
147
  ...(typeof args.reason === "string" ? { reason: args.reason } : {}),
147
148
  }, progressToken);
148
149
  }
150
+ // The split tools. handleUsePlatform already takes the method as a parameter,
151
+ // so the method is supplied HERE rather than by the model — which is what
152
+ // makes read_platform genuinely read-only.
153
+ if (name === "read_platform" || name === "write_platform" || name === "delete_platform") {
154
+ if (!args || typeof args.platform !== "string" || typeof args.endpoint !== "string" || typeof args.scope !== "string") {
155
+ return errorContent("Invalid or missing arguments: platform, endpoint, scope are required");
156
+ }
157
+ let method;
158
+ if (name === "read_platform") {
159
+ method = "GET";
160
+ }
161
+ else if (name === "delete_platform") {
162
+ method = "DELETE";
163
+ }
164
+ else {
165
+ const requested = (args.method ?? "POST");
166
+ if (requested !== "POST" && requested !== "PUT" && requested !== "PATCH") {
167
+ return errorContent(`write_platform does not accept ${requested}. Use read_platform for GET, delete_platform for DELETE.`);
168
+ }
169
+ method = requested;
170
+ }
171
+ const progressToken = request.params._meta?.progressToken;
172
+ return await handleUsePlatform(ctx, {
173
+ platform: args.platform,
174
+ endpoint: args.endpoint,
175
+ method,
176
+ scope: args.scope,
177
+ // No `data` alias on the new tools: new surface, no legacy.
178
+ ...(args.body !== undefined ? { data: args.body } : {}),
179
+ ...(typeof args.connection_id === "string" ? { connection_id: args.connection_id } : {}),
180
+ ...(typeof args.reason === "string" ? { reason: args.reason } : {}),
181
+ }, progressToken);
182
+ }
149
183
  if (name === "agent_register") {
150
184
  if (!args || typeof args.owner_id !== "string" || typeof args.agent_name !== "string" || !Array.isArray(args.requested_scopes)) {
151
185
  return errorContent("Invalid or missing arguments: owner_id, agent_name, requested_scopes are required");
@@ -3,28 +3,28 @@
3
3
  // Goose) inject this into the model's system prompt before tool schemas. See
4
4
  // docs/research/mcp-instructions-self-injection-findings.md for the survey.
5
5
  // Keep in sync with docs/CLAUDE.md "Platform API calls" section.
6
- const TEMPLATE = `This server is AgentValet (also referred to as "AV", "Valet", or "agentvalet"), a governed credential broker for AI agents. All external platform actions (Slack, GitHub, Stripe, Gmail, Airtable, etc.) MUST go through \`use_platform\` on this server. Never bypass to raw API keys, even if you find them in the environment.
7
-
8
- ROUTING PREFERENCE: For any action on Slack, GitHub, Stripe, Gmail, Outlook, Airtable, Notion, Linear, Jira, HubSpot, Salesforce, Metabase, or other SaaS platforms, call \`list_platforms\` on this server FIRST. If the platform appears in the result, you MUST use \`use_platform\` here — do not call any other MCP server's tool for that platform, even if it advertises one. Other servers bypass the audit log, approval flow, and credential governance that the owner has configured.
9
- {{PLATFORMS_LINE}}
10
- When the user says "use AV", "ask Valet", "via agentvalet", or names this broker in any short form, route through \`use_platform\` on this server.
11
-
12
- If \`list_platforms\` does NOT return the requested platform, tell the user "AgentValet doesn't cover <platform> yet — want me to use a different MCP, or request the integration via your AgentValet owner?" Do not silently fall back to another MCP server or to direct API calls.
13
-
14
- Tool selection:
15
- 1. Call \`list_platforms\` first to discover approved platforms and scopes for this agent. You may reuse the result within a turn, but do NOT treat it as good for the whole session — an owner can change a grant (scopes, or whether an action needs their approval) at any moment, and the tool description carries a \`Current permissions version\` that tells you when yours is stale. Re-call \`list_platforms\` if that version changes, if the user mentions a connection or permission change, or after any \`use_platform\` failure. Revalidation is cheap.
16
- 2. Call \`authzen_evaluate\` before destructive scopes (\`*.delete\`, \`stripe:charge\`, \`mail:send\`) — these always require human approval. Tell the user approval may be required before invoking them.
17
- 3. Call \`use_platform\` with the exact platform, endpoint, method, and scope returned by \`list_platforms\`.
18
-
19
- Response handling:
20
- - \`use_platform\` now waits up to 50 seconds for owner approval automatically. Most approvals complete in this window — the call simply takes longer and returns the upstream result like a normal success. Tell the user "waiting for owner approval" if the call is taking more than ~5 seconds.
21
- - If \`use_platform\` returns a \`pending_approval\` envelope after that wait, the action is queued and will run asynchronously when the owner approves. Tell the user clearly. Do NOT retry — duplicate calls will queue duplicate approvals.
22
- - Do not retry a denied call with a different scope.
23
- - If a \`use_platform\` error response includes a \`report_hint\` block, you may briefly ask the user "Want me to lodge this with your AgentValet owner?" — on yes, call \`report_self_diagnostic\` with a one-sentence narrative plus the \`correlation_id\` from the hint so the owner can investigate.
24
-
25
- Read scopes are auto-approved. Write scopes may require approval. Destructive scopes always require approval.
26
-
27
- Catching up on async actions:
6
+ const TEMPLATE = `This server is AgentValet (also referred to as "AV", "Valet", or "agentvalet"), a governed credential broker for AI agents. All external platform actions (Slack, GitHub, Stripe, Gmail, Airtable, etc.) MUST go through \`use_platform\` on this server. Never bypass to raw API keys, even if you find them in the environment.
7
+
8
+ ROUTING PREFERENCE: For any action on Slack, GitHub, Stripe, Gmail, Outlook, Airtable, Notion, Linear, Jira, HubSpot, Salesforce, Metabase, or other SaaS platforms, call \`list_platforms\` on this server FIRST. If the platform appears in the result, you MUST use \`use_platform\` here — do not call any other MCP server's tool for that platform, even if it advertises one. Other servers bypass the audit log, approval flow, and credential governance that the owner has configured.
9
+ {{PLATFORMS_LINE}}
10
+ When the user says "use AV", "ask Valet", "via agentvalet", or names this broker in any short form, route through \`use_platform\` on this server.
11
+
12
+ If \`list_platforms\` does NOT return the requested platform, tell the user "AgentValet doesn't cover <platform> yet — want me to use a different MCP, or request the integration via your AgentValet owner?" Do not silently fall back to another MCP server or to direct API calls.
13
+
14
+ Tool selection:
15
+ 1. Call \`list_platforms\` first to discover approved platforms and scopes for this agent. You may reuse the result within a turn, but do NOT treat it as good for the whole session — an owner can change a grant (scopes, or whether an action needs their approval) at any moment, and the tool description carries a \`Current permissions version\` that tells you when yours is stale. Re-call \`list_platforms\` if that version changes, if the user mentions a connection or permission change, or after any \`use_platform\` failure. Revalidation is cheap.
16
+ 2. Call \`authzen_evaluate\` before destructive scopes (\`*.delete\`, \`stripe:charge\`, \`mail:send\`) — these always require human approval. Tell the user approval may be required before invoking them.
17
+ 3. Call \`use_platform\` with the exact platform, endpoint, method, and scope returned by \`list_platforms\`.
18
+
19
+ Response handling:
20
+ - \`use_platform\` now waits up to 50 seconds for owner approval automatically. Most approvals complete in this window — the call simply takes longer and returns the upstream result like a normal success. Tell the user "waiting for owner approval" if the call is taking more than ~5 seconds.
21
+ - If \`use_platform\` returns a \`pending_approval\` envelope after that wait, the action is queued and will run asynchronously when the owner approves. Tell the user clearly. Do NOT retry — duplicate calls will queue duplicate approvals.
22
+ - Do not retry a denied call with a different scope.
23
+ - If a \`use_platform\` error response includes a \`report_hint\` block, you may briefly ask the user "Want me to lodge this with your AgentValet owner?" — on yes, call \`report_self_diagnostic\` with a one-sentence narrative plus the \`correlation_id\` from the hint so the owner can investigate.
24
+
25
+ Read scopes are auto-approved. Write scopes may require approval. Destructive scopes always require approval.
26
+
27
+ Catching up on async actions:
28
28
  - If the user mentions a previous action ("did the Slack post go through?", "what happened to that earlier request?") OR if the previous \`use_platform\` returned a \`pending_approval\` envelope, call \`list_my_pending_actions\` to surface what's pending and what's recently completed. Tell the user the result naturally — don't dump the JSON.`;
29
29
  /**
30
30
  * Render the instructions string. If a platform list is provided, the
@@ -9,7 +9,8 @@
9
9
  // nothing ever told the agent the spec had moved.
10
10
  //
11
11
  // GET /v1/agent/permissions returns a deterministic `version` hash over the
12
- // effective spec (scopes + requireApproval + connections). We poll it with
12
+ // effective spec (scopes + requireApproval + policy-level approvalScopes +
13
+ // connections incl. per-connection requireApproval). We poll it with
13
14
  // If-None-Match, so an unchanged spec costs a 304 with no body. When the hash
14
15
  // does move we emit notifications/tools/list_changed; the host re-reads
15
16
  // tools/list, and because the list_platforms description is stamped with the
@@ -7,7 +7,7 @@
7
7
  export const ALLOWED_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
8
8
  export const LIST_PLATFORMS_TOOL = {
9
9
  name: "list_platforms",
10
- description: "list_platforms: List the platforms and permission scopes this agent has access to.\nInput: None.\nReturns: { platforms: [{ platformId, platformName, scopes, requireApproval, connections? }], version: \"<hex>\" }. A platform includes `connections` only when it has 2+ usable accounts; pass the chosen connection_id to use_platform (omit for the default).\nVersion: a deterministic hash over the effective spec — it changes whenever the platform set, the scopes, or the requireApproval flags change. Compare it against the `Current permissions version` stamped on this description: if they differ, your cached result is stale and you must call list_platforms again before trusting it.\nAuth: Bearer JWT.",
10
+ description: "list_platforms: List the platforms and permission scopes this agent has access to.\nInput: None.\nReturns: { platforms: [{ platformId, platformName, scopes, requireApproval, approvalScopes?, connections? }], version: \"<hex>\" }. A platform includes `connections` only when it has 2+ usable accounts; pass the chosen connection_id to use_platform (omit for the default).\nApproval: a call needs human approval if the platform's requireApproval is true (grant-level: every call prompts), if the chosen connection's requireApproval is true, or if the scope is listed in approvalScopes (policy-level: just those scopes prompt). approvalScopes is omitted when no scope is policy-gated.\nVersion: a deterministic hash over the effective spec — it changes whenever the platform set, the scopes, the approval requirements (grant or policy), or the connections change. Compare it against the `Current permissions version` stamped on this description: if they differ, your cached result is stale and you must call list_platforms again before trusting it.\nAuth: Bearer JWT.",
11
11
  inputSchema: { type: "object", properties: {} },
12
12
  outputSchema: {
13
13
  type: "object",
@@ -21,6 +21,11 @@ export const LIST_PLATFORMS_TOOL = {
21
21
  platformName: { type: "string" },
22
22
  scopes: { type: "array", items: { type: "string" } },
23
23
  requireApproval: { type: "boolean" },
24
+ approvalScopes: {
25
+ type: "array",
26
+ description: "Present only when the owner's policy or an org guardrail gates some scopes on human approval. Subset of `scopes`: calls under these scopes prompt the owner even when requireApproval is false.",
27
+ items: { type: "string" },
28
+ },
24
29
  connections: {
25
30
  type: "array",
26
31
  description: "Present only when this platform has 2+ usable connections (e.g. two GitHub orgs). Pass the chosen connection_id to use_platform; omit to use the default connection.",
@@ -30,6 +35,7 @@ export const LIST_PLATFORMS_TOOL = {
30
35
  connection_id: { type: "string" },
31
36
  label: { type: "string" },
32
37
  is_default: { type: "boolean" },
38
+ requireApproval: { type: "boolean" },
33
39
  scopes: { type: "array", items: { type: "string" } },
34
40
  },
35
41
  required: ["connection_id", "label"],
@@ -87,6 +93,89 @@ export const USE_PLATFORM_TOOL = {
87
93
  required: ["platform", "endpoint", "method", "scope"],
88
94
  },
89
95
  };
96
+ // --- The read/write/delete split -------------------------------------------
97
+ //
98
+ // Descriptions are copied VERBATIM from apps/proxy/src/mcp/tools.ts so the two
99
+ // servers cannot drift. read_platform and delete_platform declare no `method`
100
+ // property at all: the method is supplied at dispatch, which is what makes the
101
+ // readOnlyHint annotation enforced rather than merely promised.
102
+ export const READ_PLATFORM_TOOL = {
103
+ name: "read_platform",
104
+ description: "read_platform: Read data from a platform the owner has connected, through the AgentValet proxy. Calls the platform's own public REST API (for example the GitHub REST API, the Slack Web API, the Stripe API); `endpoint` is a path in that API exactly as its documentation defines it. Always issues GET — use write_platform to create or update, and delete_platform to remove. Input: platform, endpoint, scope, connection_id (optional), reason (optional). Returns: the upstream API response body. Auth: Bearer JWT.",
105
+ inputSchema: {
106
+ type: "object",
107
+ properties: {
108
+ platform: { type: "string", description: "Platform ID (e.g. github, slack, stripe)" },
109
+ endpoint: { type: "string", description: "Path in the platform's own API (e.g. /user/repos)" },
110
+ scope: { type: "string", description: "Permission scope required for this read (e.g. repo:read)" },
111
+ connection_id: {
112
+ type: "string",
113
+ description: "Optional. Target a specific connection when a platform has more than one connected. Omit to use the default.",
114
+ },
115
+ reason: {
116
+ type: "string",
117
+ description: "Optional but strongly encouraged. One sentence on WHY you are making this call. Shown to the human approver if the call is gated. Max 500 characters; plain text.",
118
+ },
119
+ },
120
+ required: ["platform", "endpoint", "scope"],
121
+ },
122
+ };
123
+ export const WRITE_PLATFORM_TOOL = {
124
+ name: "write_platform",
125
+ description: "write_platform: Create or update data on a platform the owner has connected, through the AgentValet proxy. Calls the platform's own public REST API (for example the GitHub REST API, the Slack Web API, the Stripe API); `endpoint` is a path in that API exactly as its documentation defines it. Accepts POST, PUT or PATCH only — use read_platform for GET and delete_platform for DELETE. May block up to 50s for owner approval, then returns the approved result; otherwise returns a pending_approval envelope. Input: platform, endpoint, scope, method (optional, default POST), body (optional), connection_id (optional), reason (optional). Auth: Bearer JWT.",
126
+ inputSchema: {
127
+ type: "object",
128
+ properties: {
129
+ platform: { type: "string", description: "Platform ID (e.g. github, slack, stripe)" },
130
+ endpoint: { type: "string", description: "Path in the platform's own API (e.g. /api/chat.postMessage)" },
131
+ method: {
132
+ type: "string",
133
+ enum: ["POST", "PUT", "PATCH"],
134
+ default: "POST",
135
+ description: "POST to create, PUT to replace, PATCH to modify. Defaults to POST.",
136
+ },
137
+ scope: { type: "string", description: "Permission scope required for this write (e.g. chat:write)" },
138
+ body: {
139
+ type: "object",
140
+ description: "JSON request body, forwarded verbatim to the upstream API.",
141
+ },
142
+ connection_id: {
143
+ type: "string",
144
+ description: "Optional. Target a specific connection when a platform has more than one connected. Omit to use the default.",
145
+ },
146
+ reason: {
147
+ type: "string",
148
+ description: "Optional but strongly encouraged. One sentence on WHY you are making this call. Shown to the human approver if the call is gated. Max 500 characters; plain text.",
149
+ },
150
+ },
151
+ required: ["platform", "endpoint", "scope"],
152
+ },
153
+ };
154
+ export const DELETE_PLATFORM_TOOL = {
155
+ name: "delete_platform",
156
+ description: "delete_platform: Delete data on a platform the owner has connected, through the AgentValet proxy. Calls the platform's own public REST API (for example the GitHub REST API, the Slack Web API, the Stripe API); `endpoint` is a path in that API exactly as its documentation defines it. Always issues DELETE. This removes data and is not reversible by AgentValet. May block up to 50s for owner approval. Input: platform, endpoint, scope, body (optional), connection_id (optional), reason (optional). Auth: Bearer JWT.",
157
+ inputSchema: {
158
+ type: "object",
159
+ properties: {
160
+ platform: { type: "string", description: "Platform ID (e.g. github, slack, stripe)" },
161
+ endpoint: { type: "string", description: "Path in the platform's own API (e.g. /repos/owner/name)" },
162
+ scope: { type: "string", description: "Permission scope required for this delete (e.g. repo:delete)" },
163
+ body: {
164
+ type: "object",
165
+ description: "Optional JSON request body, forwarded verbatim.",
166
+ },
167
+ connection_id: {
168
+ type: "string",
169
+ description: "Optional. Target a specific connection when a platform has more than one connected. Omit to use the default.",
170
+ },
171
+ reason: {
172
+ type: "string",
173
+ description: "Optional but strongly encouraged. One sentence on WHY you are deleting this. Shown to the human approver if the call is gated. Max 500 characters; plain text.",
174
+ },
175
+ },
176
+ required: ["platform", "endpoint", "scope"],
177
+ },
178
+ };
90
179
  export const AGENT_REGISTER_TOOL = {
91
180
  name: "agent_register",
92
181
  description: "agent_register: Self-register this agent with an owner. No auth required.\nInput: owner_id (string), agent_name (string), requested_scopes (array of {platformId, scopes}).\nReturns: registration_token, poll_url, client_id, scope, expires_in.\nAuth: None.",
@@ -289,6 +378,9 @@ export const REQUEST_PLATFORM_ACCESS_TOOL = {
289
378
  export const ALL_TOOLS = [
290
379
  LIST_PLATFORMS_TOOL,
291
380
  USE_PLATFORM_TOOL,
381
+ READ_PLATFORM_TOOL,
382
+ WRITE_PLATFORM_TOOL,
383
+ DELETE_PLATFORM_TOOL,
292
384
  AGENT_REGISTER_TOOL,
293
385
  AGENT_STATUS_TOOL,
294
386
  AUTHZEN_EVALUATE_TOOL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvalet/mcp-server",
3
- "version": "1.6.1",
3
+ "version": "1.8.0",
4
4
  "description": "AgentValet MCP server — lets AI agents call approved platforms via the AgentValet proxy",
5
5
  "mcpName": "io.github.agentvalet/mcp-server",
6
6
  "type": "module",
@@ -12,6 +12,14 @@
12
12
  "dist",
13
13
  "README.md"
14
14
  ],
15
+ "scripts": {
16
+ "dev": "tsx src/index.ts",
17
+ "build": "tsc",
18
+ "start": "node dist/index.js",
19
+ "test": "vitest run",
20
+ "typecheck": "tsc --noEmit",
21
+ "prepublishOnly": "node ../../scripts/no-secrets.mjs && npm run build && node ../../scripts/no-workspace-protocol.mjs"
22
+ },
15
23
  "dependencies": {
16
24
  "@modelcontextprotocol/sdk": "^1.0.0",
17
25
  "jose": "^5.10.0"
@@ -37,12 +45,5 @@
37
45
  "agentvalet"
38
46
  ],
39
47
  "license": "MIT",
40
- "homepage": "https://github.com/AgentValet/AgentValet#readme",
41
- "scripts": {
42
- "dev": "tsx src/index.ts",
43
- "build": "tsc",
44
- "start": "node dist/index.js",
45
- "test": "vitest run",
46
- "typecheck": "tsc --noEmit"
47
- }
48
- }
48
+ "homepage": "https://github.com/AgentValet/AgentValet#readme"
49
+ }