@agentvalet/mcp-server 1.4.0 → 1.6.1

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,67 +1,70 @@
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 |
53
- | `agent_register` | None | Self-register a new agent with an owner |
54
- | `agent_status` | None | Poll registration approval status |
55
- | `authzen_evaluate` | None | Check if this agent has access to a platform scope |
56
-
57
- ## Transports
58
-
59
- **STDIO (default)** — compatible with all MCP hosts (Claude Code, Cursor, Codex CLI).
60
-
61
- **HTTP** — set `MCP_TRANSPORT=http` and optionally `MCP_PORT=3100`. Uses `StreamableHTTPServerTransport`.
62
-
63
- ## Architecture
64
-
65
- 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.
66
-
67
- 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
+ | `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.
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ import { signJWT } from "./auth.js";
24
24
  import { ALLOWED_METHODS, ALL_TOOLS } from "./tools/schemas.js";
25
25
  import { handleListPlatforms, handleUsePlatform, handleAgentRegister, handleAgentStatus, handleAuthzenEvaluate, handleListMyPendingActions, handleReportSelfDiagnostic, handleRequestPlatformAccess, } from "./tools/handlers.js";
26
26
  import { errorContent } from "./net.js";
27
+ import { getPermissionsVersion, recordPermissionsVersion, startPermissionsWatcher, } from "./permissions-watcher.js";
27
28
  // ---------------------------------------------------------------------------
28
29
  // Startup env validation
29
30
  // ---------------------------------------------------------------------------
@@ -40,7 +41,12 @@ process.stderr.write(`[mcp-server] config ok | agent=${AGENT_ID} | owner=${OWNER
40
41
  // ---------------------------------------------------------------------------
41
42
  // MCP server setup
42
43
  // ---------------------------------------------------------------------------
43
- const server = new Server({ name: "agentvalet", version: "1.0.0" }, { capabilities: { tools: {} }, instructions: renderInstructions(undefined) });
44
+ const server = new Server({ name: "agentvalet", version: "1.0.0" },
45
+ // listChanged: the permissions watcher pushes notifications/tools/list_changed
46
+ // when the agent's effective platform spec moves under it (see
47
+ // permissions-watcher.ts). Declaring the capability is what makes the SDK
48
+ // allow that notification.
49
+ { capabilities: { tools: { listChanged: true } }, instructions: renderInstructions(undefined) });
44
50
  // The config + server bundle threaded into auth + handlers (see context.ts) —
45
51
  // keeps those modules free of globals.
46
52
  const ctx = {
@@ -65,19 +71,42 @@ void (async () => {
65
71
  const token = await signJWT(ctx);
66
72
  const ac = new AbortController();
67
73
  const timer = setTimeout(() => ac.abort(), 4_000);
68
- await fetch(`${PROXY_URL}/v1/agent/permissions`, {
74
+ const res = await fetch(`${PROXY_URL}/v1/agent/permissions`, {
69
75
  method: "GET",
70
76
  headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
71
77
  signal: ac.signal,
72
78
  }).finally(() => clearTimeout(timer));
79
+ // Seed the watcher's baseline so the first poll compares against the spec
80
+ // as it was at boot, not against "unknown".
81
+ if (res.ok) {
82
+ const parsed = (await res.json());
83
+ recordPermissionsVersion(parsed?.data?.version ?? parsed?.version);
84
+ }
73
85
  }
74
86
  catch {
75
87
  // best-effort warmup only
76
88
  }
77
89
  })().catch(() => { });
78
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
79
- tools: ALL_TOOLS,
80
- }));
90
+ // Stamp list_platforms with the current permissions version. This is the half
91
+ // of the staleness fix that actually reaches the model: after a
92
+ // tools/list_changed push the host re-reads tools/list, and a description that
93
+ // genuinely differs from the one already in context is what tells the model its
94
+ // cached platform spec is no longer the live one.
95
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
96
+ const version = getPermissionsVersion();
97
+ if (!version)
98
+ return { tools: ALL_TOOLS };
99
+ return {
100
+ tools: ALL_TOOLS.map((tool) => tool.name === "list_platforms"
101
+ ? {
102
+ ...tool,
103
+ description: `${tool.description}\nCurrent permissions version: ${version}. If you are holding a ` +
104
+ `list_platforms result from a different version, it is STALE — call list_platforms ` +
105
+ `again before relying on its scopes or requireApproval flags.`,
106
+ }
107
+ : tool),
108
+ };
109
+ });
81
110
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
82
111
  const { name, arguments: args } = request.params;
83
112
  if (name === "list_platforms") {
@@ -114,6 +143,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
114
143
  scope: args.scope,
115
144
  data: bodyArg,
116
145
  ...(typeof args.connection_id === "string" ? { connection_id: args.connection_id } : {}),
146
+ ...(typeof args.reason === "string" ? { reason: args.reason } : {}),
117
147
  }, progressToken);
118
148
  }
119
149
  if (name === "agent_register") {
@@ -166,3 +196,6 @@ else {
166
196
  const transport = new StdioServerTransport();
167
197
  await server.connect(transport);
168
198
  }
199
+ // Started only after the transport is connected — notifications have nowhere to
200
+ // go before that. No-op without credentials or when AV_PERMISSIONS_POLL_MS=0.
201
+ startPermissionsWatcher(ctx);
@@ -12,7 +12,7 @@ When the user says "use AV", "ask Valet", "via agentvalet", or names this broker
12
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
13
 
14
14
  Tool selection:
15
- 1. Call \`list_platforms\` first to discover approved platforms and scopes for this agent. Cache the result for the session — re-call only if the user mentions a new connection or after a \`use_platform\` failure.
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
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
17
  3. Call \`use_platform\` with the exact platform, endpoint, method, and scope returned by \`list_platforms\`.
18
18
 
@@ -0,0 +1,132 @@
1
+ // apps/mcp-server/src/permissions-watcher.ts
2
+ //
3
+ // Keeps the host's view of the agent's platform spec from going stale.
4
+ //
5
+ // The problem this exists for: an owner flips a grant in the dashboard (say,
6
+ // require_approval on Slack) mid-session. The agent had already called
7
+ // list_platforms and cached the answer in its context, so it kept reasoning
8
+ // from the pre-change spec — the proxy enforced the new rule at call time, but
9
+ // nothing ever told the agent the spec had moved.
10
+ //
11
+ // GET /v1/agent/permissions returns a deterministic `version` hash over the
12
+ // effective spec (scopes + requireApproval + connections). We poll it with
13
+ // If-None-Match, so an unchanged spec costs a 304 with no body. When the hash
14
+ // does move we emit notifications/tools/list_changed; the host re-reads
15
+ // tools/list, and because the list_platforms description is stamped with the
16
+ // current version (see index.ts), the description the model sees actually
17
+ // differs — which is what gets the stale cache invalidated in practice. A bare
18
+ // list_changed on an otherwise-identical tool list would be a no-op.
19
+ //
20
+ // Note this only works on a long-lived transport. The in-proxy MCP endpoint
21
+ // (apps/proxy/src/routes/mcp.ts) is deliberately stateless — a fresh Server per
22
+ // request — so it has no server→client channel and cannot push at all; there,
23
+ // cheap revalidation via the 304 path is the whole story.
24
+ import { signJWT } from "./auth.js";
25
+ import { fetchWithTimeout } from "./net.js";
26
+ const DEFAULT_POLL_MS = 60_000;
27
+ // Floor so a typo in the env var can't turn an agent into a polling hammer
28
+ // against the proxy.
29
+ const MIN_POLL_MS = 10_000;
30
+ let currentVersion = null;
31
+ let timer = null;
32
+ export function getPermissionsVersion() {
33
+ return currentVersion;
34
+ }
35
+ /**
36
+ * Record a version observed elsewhere (a normal list_platforms tool call).
37
+ * Returns true when this is a CHANGE from a previously-known version — the
38
+ * first observation only establishes the baseline and is not a change.
39
+ */
40
+ export function recordPermissionsVersion(version) {
41
+ if (!version || typeof version !== "string")
42
+ return false;
43
+ const hadBaseline = currentVersion !== null;
44
+ const changed = hadBaseline && version !== currentVersion;
45
+ currentVersion = version;
46
+ return changed;
47
+ }
48
+ /** Test seam: forget everything the watcher has learned. */
49
+ export function resetPermissionsVersion() {
50
+ currentVersion = null;
51
+ }
52
+ export function pollIntervalMs(raw = process.env.AV_PERMISSIONS_POLL_MS) {
53
+ if (raw === undefined || raw === "")
54
+ return DEFAULT_POLL_MS;
55
+ const parsed = Number(raw);
56
+ if (!Number.isFinite(parsed) || parsed <= 0)
57
+ return 0; // 0 / invalid ⇒ disabled
58
+ return Math.max(parsed, MIN_POLL_MS);
59
+ }
60
+ /**
61
+ * One revalidation round-trip. Exported for tests. Returns true when the spec
62
+ * changed (and a notification was emitted).
63
+ */
64
+ export async function checkPermissionsVersion(ctx) {
65
+ if (ctx.AGENT_PRIVATE_KEY_RAW === null)
66
+ return false;
67
+ let response;
68
+ try {
69
+ const token = await signJWT(ctx);
70
+ const headers = {
71
+ Authorization: `Bearer ${token}`,
72
+ "Content-Type": "application/json",
73
+ };
74
+ if (currentVersion)
75
+ headers["If-None-Match"] = `"${currentVersion}"`;
76
+ response = await fetchWithTimeout(`${ctx.PROXY_URL}/v1/agent/permissions`, { method: "GET", headers }, 10_000);
77
+ }
78
+ catch {
79
+ return false; // transient — try again next tick
80
+ }
81
+ // Unchanged: the whole point of the conditional request.
82
+ if (response.status === 304)
83
+ return false;
84
+ if (!response.ok)
85
+ return false;
86
+ let version;
87
+ try {
88
+ const parsed = (await response.json());
89
+ const inner = (parsed && typeof parsed === "object" && "data" in parsed
90
+ ? parsed.data
91
+ : parsed);
92
+ if (inner && typeof inner.version === "string")
93
+ version = inner.version;
94
+ }
95
+ catch {
96
+ return false;
97
+ }
98
+ if (!recordPermissionsVersion(version))
99
+ return false;
100
+ try {
101
+ await ctx.server.notification({ method: "notifications/tools/list_changed" });
102
+ }
103
+ catch {
104
+ // Best-effort: a host that doesn't accept the notification still gets the
105
+ // corrected spec the next time it calls list_platforms.
106
+ }
107
+ return true;
108
+ }
109
+ /**
110
+ * Start background revalidation. No-op without credentials or when polling is
111
+ * disabled. The timer is unref'd so it can never hold the process open.
112
+ */
113
+ export function startPermissionsWatcher(ctx) {
114
+ if (timer)
115
+ return;
116
+ if (ctx.AGENT_PRIVATE_KEY_RAW === null)
117
+ return;
118
+ const interval = pollIntervalMs();
119
+ if (interval === 0)
120
+ return;
121
+ timer = setInterval(() => {
122
+ void checkPermissionsVersion(ctx).catch(() => { });
123
+ }, interval);
124
+ // `unref` is absent in some non-Node runtimes; guard rather than assume.
125
+ timer.unref?.();
126
+ }
127
+ export function stopPermissionsWatcher() {
128
+ if (!timer)
129
+ return;
130
+ clearInterval(timer);
131
+ timer = null;
132
+ }
@@ -6,6 +6,7 @@
6
6
  // module globals. Behavior is unchanged — pinned by test/introspection.test.ts.
7
7
  import { errorContent, jsonContent, tryParseJson, safeJsonParse, sleep, diagnoseNetworkError, fetchWithTimeout, } from "../net.js";
8
8
  import { requireCredentials, fetchWithAuth } from "../auth.js";
9
+ import { recordPermissionsVersion } from "../permissions-watcher.js";
9
10
  export async function handleListPlatforms(ctx) {
10
11
  const gate = await requireCredentials(ctx);
11
12
  if (gate)
@@ -29,6 +30,9 @@ export async function handleListPlatforms(ctx) {
29
30
  ? parsed.data
30
31
  : parsed;
31
32
  if (inner && typeof inner === "object") {
33
+ // Keep the watcher's baseline in step with what the agent was just told, so
34
+ // a manual refresh doesn't trigger a spurious "changed" notification.
35
+ recordPermissionsVersion(inner.version);
32
36
  return {
33
37
  content: [{ type: "text", text: body }],
34
38
  structuredContent: inner,
@@ -91,6 +95,9 @@ export async function handleUsePlatform(ctx, params, progressToken) {
91
95
  scope: params.scope,
92
96
  ...(params.data !== undefined && { data: params.data }),
93
97
  ...(params.connection_id ? { connection_id: params.connection_id } : {}),
98
+ // Agent-supplied justification. Forwarded verbatim; the proxy normalizes
99
+ // and caps it before it reaches the approver's screen.
100
+ ...(params.reason ? { reason: params.reason } : {}),
94
101
  };
95
102
  let response;
96
103
  try {
@@ -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 that only changes when the platform set or scopes change. Cache the value across calls in the same session — only refresh when you suspect platforms have changed (e.g. user mentions a new connection).\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, 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.",
11
11
  inputSchema: { type: "object", properties: {} },
12
12
  outputSchema: {
13
13
  type: "object",
@@ -46,7 +46,7 @@ export const LIST_PLATFORMS_TOOL = {
46
46
  };
47
47
  export const USE_PLATFORM_TOOL = {
48
48
  name: "use_platform",
49
- description: "use_platform: Call an external platform API (Airtable, GitHub, Slack, Metabase, etc.) through the AgentValet proxy.\nInput: platform (string), endpoint (string), method (GET|POST|PUT|PATCH|DELETE), scope (string), body (object, optional — JSON request body for POST/PUT/PATCH/DELETE).\nReturns: upstream API response body. May take up to 50 seconds when the action requires owner approval — the call will block while we wait, then return the approved result transparently. If approval doesn't land in time, returns a `pending_approval` envelope and the action runs asynchronously; the user is notified when it completes.\nAuth: Bearer JWT.\nNote: legacy clients passing `data` instead of `body` are still accepted for backwards compatibility, but `body` is the canonical name.",
49
+ description: "use_platform: Call an external platform API (Airtable, GitHub, Slack, Metabase, etc.) through the AgentValet proxy.\nInput: platform (string), endpoint (string), method (GET|POST|PUT|PATCH|DELETE), scope (string), body (object, optional — JSON request body for POST/PUT/PATCH/DELETE), reason (string, optional — why you are making this call; shown to the human approver when the action is gated).\nReturns: upstream API response body. May take up to 50 seconds when the action requires owner approval — the call will block while we wait, then return the approved result transparently. If approval doesn't land in time, returns a `pending_approval` envelope and the action runs asynchronously; the user is notified when it completes.\nAuth: Bearer JWT.\nNote: legacy clients passing `data` instead of `body` are still accepted for backwards compatibility, but `body` is the canonical name.",
50
50
  inputSchema: {
51
51
  type: "object",
52
52
  properties: {
@@ -79,6 +79,10 @@ export const USE_PLATFORM_TOOL = {
79
79
  type: "string",
80
80
  description: "Optional. Target a specific connection when a platform has more than one connected (e.g. two GitHub orgs). Value is the connection id shown in the dashboard. Omit to use the default connection.",
81
81
  },
82
+ reason: {
83
+ type: "string",
84
+ description: "Optional but strongly encouraged. One sentence on WHY you are making this call. If the action requires owner approval, this is shown to the human who decides — without it their approval is a blind yes/no. Max 500 characters (longer is truncated). Plain text; markup is not rendered.",
85
+ },
82
86
  },
83
87
  required: ["platform", "endpoint", "method", "scope"],
84
88
  },
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@agentvalet/mcp-server",
3
- "version": "1.4.0",
3
+ "version": "1.6.1",
4
4
  "description": "AgentValet MCP server — lets AI agents call approved platforms via the AgentValet proxy",
5
+ "mcpName": "io.github.agentvalet/mcp-server",
5
6
  "type": "module",
6
7
  "main": "dist/index.js",
7
8
  "bin": {
@@ -11,14 +12,6 @@
11
12
  "dist",
12
13
  "README.md"
13
14
  ],
14
- "scripts": {
15
- "dev": "tsx src/index.ts",
16
- "build": "tsc",
17
- "start": "node dist/index.js",
18
- "test": "vitest run",
19
- "typecheck": "tsc --noEmit",
20
- "prepublishOnly": "npm run build"
21
- },
22
15
  "dependencies": {
23
16
  "@modelcontextprotocol/sdk": "^1.0.0",
24
17
  "jose": "^5.10.0"
@@ -34,8 +27,8 @@
34
27
  },
35
28
  "repository": {
36
29
  "type": "git",
37
- "url": "git+https://github.com/MCSEdwin/agentvalet.git",
38
- "directory": "apps/mcp-server"
30
+ "url": "git+https://github.com/AgentValet/AgentValet.git",
31
+ "directory": "packages/mcp-server"
39
32
  },
40
33
  "keywords": [
41
34
  "ai",
@@ -43,5 +36,13 @@
43
36
  "mcp",
44
37
  "agentvalet"
45
38
  ],
46
- "license": "MIT"
47
- }
39
+ "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
+ }