@interf/gateway 0.0.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/dist/cli.js +7 -0
- package/dist/server.js +401 -0
- package/package.json +25 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { createServer } from "./server.js";
|
|
4
|
+
const server = createServer();
|
|
5
|
+
const transport = new StdioServerTransport();
|
|
6
|
+
await server.connect(transport);
|
|
7
|
+
console.error("interf-gateway running on stdio");
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import YAML from "yaml";
|
|
4
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
5
|
+
const SERVER_INSTRUCTIONS = `You are connected to the Interf Gateway — the Agent Readiness Protocol.
|
|
6
|
+
|
|
7
|
+
Interf helps coding agents understand what it takes for their AI-powered tool to be adopted
|
|
8
|
+
by real enterprises. When a coding agent builds something (a CRM automation, an internal tool,
|
|
9
|
+
a data pipeline), Interf answers: "What does an enterprise need before they can actually deploy this?"
|
|
10
|
+
|
|
11
|
+
## What you can do with Interf
|
|
12
|
+
|
|
13
|
+
1. **Generate an interf.yaml manifest** — Use get_protocol_guidance to learn the spec, then
|
|
14
|
+
help the user create an interf.yaml that describes their agent/tool's enterprise dependencies.
|
|
15
|
+
|
|
16
|
+
2. **Run a simulation** — Pass a manifest + enterprise profiles to run_simulation to see
|
|
17
|
+
estimated integration timelines, stakeholder requirements, and risk factors.
|
|
18
|
+
|
|
19
|
+
## Workflow
|
|
20
|
+
1. Call get_protocol_guidance to understand the protocol
|
|
21
|
+
2. Help the user define their agent's manifest (interf.yaml)
|
|
22
|
+
3. Run simulations against target enterprise profiles
|
|
23
|
+
`;
|
|
24
|
+
const PROTOCOL_GUIDANCE = `# Interf Protocol — Agent Readiness Specification
|
|
25
|
+
|
|
26
|
+
## Overview
|
|
27
|
+
An \`interf.yaml\` manifest declares everything an AI agent/tool needs from an enterprise
|
|
28
|
+
environment to function. It's the bridge between "works on my laptop" and "deployed in prod."
|
|
29
|
+
|
|
30
|
+
## interf.yaml Schema
|
|
31
|
+
|
|
32
|
+
\`\`\`yaml
|
|
33
|
+
name: string # Agent/tool name
|
|
34
|
+
version: string # Semver
|
|
35
|
+
description: string # What it does
|
|
36
|
+
|
|
37
|
+
dependencies:
|
|
38
|
+
- type: string # One of: api, database, auth, storage, network, secret, approval, compliance
|
|
39
|
+
name: string # Human-readable name
|
|
40
|
+
description: string # What this dependency is for
|
|
41
|
+
required: boolean # Is this blocking?
|
|
42
|
+
config: # Type-specific configuration
|
|
43
|
+
# For api: endpoint, method, auth_type, scopes
|
|
44
|
+
# For database: engine, access_level (read/write/admin)
|
|
45
|
+
# For auth: provider, protocol (oauth2/saml/api_key), scopes
|
|
46
|
+
# For storage: type (s3/gcs/local), access_level
|
|
47
|
+
# For network: hosts, ports, protocol
|
|
48
|
+
# For secret: names (list of env vars or vault paths)
|
|
49
|
+
# For approval: approver_role, justification
|
|
50
|
+
# For compliance: frameworks (SOC2/HIPAA/GDPR), controls
|
|
51
|
+
|
|
52
|
+
capabilities:
|
|
53
|
+
- string # What the agent can do (e.g. "read_contacts", "send_email")
|
|
54
|
+
|
|
55
|
+
risk_level: low | medium | high | critical
|
|
56
|
+
\`\`\`
|
|
57
|
+
|
|
58
|
+
## Example interf.yaml
|
|
59
|
+
|
|
60
|
+
\`\`\`yaml
|
|
61
|
+
name: crm-automation-agent
|
|
62
|
+
version: 0.1.0
|
|
63
|
+
description: Automates CRM data entry and follow-up scheduling
|
|
64
|
+
|
|
65
|
+
dependencies:
|
|
66
|
+
- type: api
|
|
67
|
+
name: Salesforce API
|
|
68
|
+
description: Read/write contacts and opportunities
|
|
69
|
+
required: true
|
|
70
|
+
config:
|
|
71
|
+
endpoint: https://api.salesforce.com
|
|
72
|
+
auth_type: oauth2
|
|
73
|
+
scopes: [api, refresh_token]
|
|
74
|
+
|
|
75
|
+
- type: auth
|
|
76
|
+
name: SSO Integration
|
|
77
|
+
description: Enterprise SSO for agent authentication
|
|
78
|
+
required: true
|
|
79
|
+
config:
|
|
80
|
+
provider: okta
|
|
81
|
+
protocol: saml
|
|
82
|
+
|
|
83
|
+
- type: secret
|
|
84
|
+
name: API Credentials
|
|
85
|
+
description: Salesforce client credentials
|
|
86
|
+
required: true
|
|
87
|
+
config:
|
|
88
|
+
names: [SF_CLIENT_ID, SF_CLIENT_SECRET, SF_REFRESH_TOKEN]
|
|
89
|
+
|
|
90
|
+
- type: compliance
|
|
91
|
+
name: SOC2 Compliance
|
|
92
|
+
description: Required for handling customer PII
|
|
93
|
+
required: true
|
|
94
|
+
config:
|
|
95
|
+
frameworks: [SOC2]
|
|
96
|
+
controls: [data_encryption, audit_logging, access_review]
|
|
97
|
+
|
|
98
|
+
- type: approval
|
|
99
|
+
name: Security Review
|
|
100
|
+
description: InfoSec team must approve API access
|
|
101
|
+
required: true
|
|
102
|
+
config:
|
|
103
|
+
approver_role: security_engineer
|
|
104
|
+
justification: Agent accesses customer PII via Salesforce
|
|
105
|
+
|
|
106
|
+
capabilities:
|
|
107
|
+
- read_contacts
|
|
108
|
+
- write_contacts
|
|
109
|
+
- read_opportunities
|
|
110
|
+
- schedule_followups
|
|
111
|
+
|
|
112
|
+
risk_level: high
|
|
113
|
+
\`\`\`
|
|
114
|
+
|
|
115
|
+
## Instructions for Coding Agents
|
|
116
|
+
|
|
117
|
+
When helping a user create an interf.yaml:
|
|
118
|
+
1. Ask what the agent/tool does
|
|
119
|
+
2. Identify all external systems it needs to talk to (APIs, databases, etc.)
|
|
120
|
+
3. Identify auth requirements
|
|
121
|
+
4. Identify secrets/credentials needed
|
|
122
|
+
5. Identify compliance requirements based on data sensitivity
|
|
123
|
+
6. Identify stakeholder approvals needed
|
|
124
|
+
7. Assess overall risk level
|
|
125
|
+
8. Generate the YAML manifest
|
|
126
|
+
|
|
127
|
+
Then offer to run a simulation against target enterprise profiles.
|
|
128
|
+
`;
|
|
129
|
+
const SIMULATION_PROMPT = `You are an enterprise integration analyst. Given an agent's interf.yaml manifest and a target enterprise profile, produce a realistic deployment simulation.
|
|
130
|
+
|
|
131
|
+
For each dependency in the manifest, analyze:
|
|
132
|
+
- estimated_days: realistic business days to integrate (not just engineering — include procurement, legal, security review)
|
|
133
|
+
- stakeholders: specific roles that must be involved
|
|
134
|
+
- risks: concrete risks for this specific dependency at this specific enterprise type
|
|
135
|
+
- recommendation: actionable next step
|
|
136
|
+
|
|
137
|
+
Consider the enterprise profile carefully:
|
|
138
|
+
- Fortune 500 / large enterprise: heavy governance, CAB reviews, vendor risk assessment, 3-6 month cycles
|
|
139
|
+
- Regulated (bank, healthcare): add regulatory review, compliance mapping, audit requirements
|
|
140
|
+
- Series B / growth stage: lighter process but still has security review, maybe SOC2 in progress
|
|
141
|
+
- Startup: minimal process, mostly just engineering work
|
|
142
|
+
|
|
143
|
+
Respond ONLY with valid JSON matching this schema:
|
|
144
|
+
{
|
|
145
|
+
"profile": "the enterprise profile",
|
|
146
|
+
"summary": {
|
|
147
|
+
"total_dependencies": number,
|
|
148
|
+
"critical_path_days": number,
|
|
149
|
+
"total_stakeholders": ["role1", "role2"],
|
|
150
|
+
"overall_risk": "low|medium|high|critical",
|
|
151
|
+
"executive_summary": "2-3 sentence summary"
|
|
152
|
+
},
|
|
153
|
+
"additional_requirements": ["extra things this enterprise type needs"],
|
|
154
|
+
"dependency_analysis": [
|
|
155
|
+
{
|
|
156
|
+
"dependency": "name",
|
|
157
|
+
"type": "type",
|
|
158
|
+
"required": true,
|
|
159
|
+
"estimated_days": number,
|
|
160
|
+
"stakeholders": ["role1"],
|
|
161
|
+
"risks": ["risk1"],
|
|
162
|
+
"recommendation": "actionable advice"
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
}`;
|
|
166
|
+
// Fallback estimation tables when no API key
|
|
167
|
+
const ESTIMATES = {
|
|
168
|
+
api: {
|
|
169
|
+
baseDays: 5,
|
|
170
|
+
stakeholders: ["API platform team", "Security review"],
|
|
171
|
+
risks: ["Rate limiting", "API versioning changes", "Credential rotation"],
|
|
172
|
+
},
|
|
173
|
+
database: {
|
|
174
|
+
baseDays: 8,
|
|
175
|
+
stakeholders: ["DBA team", "Data governance"],
|
|
176
|
+
risks: ["Schema migration conflicts", "Performance impact", "Data residency"],
|
|
177
|
+
},
|
|
178
|
+
auth: {
|
|
179
|
+
baseDays: 10,
|
|
180
|
+
stakeholders: ["Identity team", "Security architect"],
|
|
181
|
+
risks: ["SSO configuration complexity", "Token lifecycle management"],
|
|
182
|
+
},
|
|
183
|
+
storage: {
|
|
184
|
+
baseDays: 4,
|
|
185
|
+
stakeholders: ["Cloud infrastructure team"],
|
|
186
|
+
risks: ["Storage cost scaling", "Data retention policies"],
|
|
187
|
+
},
|
|
188
|
+
network: {
|
|
189
|
+
baseDays: 7,
|
|
190
|
+
stakeholders: ["Network security", "Firewall team"],
|
|
191
|
+
risks: ["Firewall rule approval delays", "VPN/private link setup"],
|
|
192
|
+
},
|
|
193
|
+
secret: {
|
|
194
|
+
baseDays: 3,
|
|
195
|
+
stakeholders: ["Security operations", "Vault admin"],
|
|
196
|
+
risks: ["Secret rotation automation", "Access audit requirements"],
|
|
197
|
+
},
|
|
198
|
+
approval: {
|
|
199
|
+
baseDays: 12,
|
|
200
|
+
stakeholders: ["Designated approver", "Legal (if PII involved)"],
|
|
201
|
+
risks: ["Approval bottlenecks", "Re-approval on scope changes"],
|
|
202
|
+
},
|
|
203
|
+
compliance: {
|
|
204
|
+
baseDays: 20,
|
|
205
|
+
stakeholders: ["Compliance officer", "Legal", "External auditor"],
|
|
206
|
+
risks: ["Audit timeline uncertainty", "Control gap remediation"],
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
const PROFILE_MULTIPLIERS = {
|
|
210
|
+
"fortune 500": {
|
|
211
|
+
multiplier: 2.5,
|
|
212
|
+
extras: ["Change Advisory Board review", "Vendor risk assessment", "Procurement cycle"],
|
|
213
|
+
},
|
|
214
|
+
"fortune 500 bank": {
|
|
215
|
+
multiplier: 3.0,
|
|
216
|
+
extras: ["OCC/FFIEC regulatory review", "Third-party risk management", "Model risk assessment"],
|
|
217
|
+
},
|
|
218
|
+
enterprise: {
|
|
219
|
+
multiplier: 2.0,
|
|
220
|
+
extras: ["Change management process", "Architecture review board"],
|
|
221
|
+
},
|
|
222
|
+
"series b": {
|
|
223
|
+
multiplier: 1.2,
|
|
224
|
+
extras: ["Lightweight security review"],
|
|
225
|
+
},
|
|
226
|
+
"series b fintech": {
|
|
227
|
+
multiplier: 1.5,
|
|
228
|
+
extras: ["PCI-DSS considerations", "State licensing check"],
|
|
229
|
+
},
|
|
230
|
+
startup: {
|
|
231
|
+
multiplier: 1.0,
|
|
232
|
+
extras: [],
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
function matchProfile(profile) {
|
|
236
|
+
const lower = profile.toLowerCase();
|
|
237
|
+
for (const [key, val] of Object.entries(PROFILE_MULTIPLIERS)) {
|
|
238
|
+
if (lower.includes(key))
|
|
239
|
+
return val;
|
|
240
|
+
}
|
|
241
|
+
return { multiplier: 1.5, extras: ["Standard enterprise review"] };
|
|
242
|
+
}
|
|
243
|
+
function fallbackSimulation(manifest, profile) {
|
|
244
|
+
const { multiplier, extras } = matchProfile(profile);
|
|
245
|
+
const deps = manifest.dependencies || [];
|
|
246
|
+
const analyses = deps.map((dep) => {
|
|
247
|
+
const est = ESTIMATES[dep.type] || ESTIMATES["api"];
|
|
248
|
+
const days = Math.ceil(est.baseDays * multiplier);
|
|
249
|
+
return {
|
|
250
|
+
dependency: dep.name,
|
|
251
|
+
type: dep.type,
|
|
252
|
+
required: dep.required ?? true,
|
|
253
|
+
estimated_days: days,
|
|
254
|
+
stakeholders: est.stakeholders,
|
|
255
|
+
risks: est.risks,
|
|
256
|
+
recommendation: days > 15
|
|
257
|
+
? "Start early — this is on the critical path"
|
|
258
|
+
: days > 7
|
|
259
|
+
? "Plan ahead — requires coordination"
|
|
260
|
+
: "Straightforward — can parallelize",
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
const totalDays = Math.max(...analyses.map((a) => a.estimated_days), 0);
|
|
264
|
+
const parallelDays = Math.ceil(totalDays * 1.2);
|
|
265
|
+
return {
|
|
266
|
+
profile,
|
|
267
|
+
summary: {
|
|
268
|
+
total_dependencies: deps.length,
|
|
269
|
+
critical_path_days: parallelDays,
|
|
270
|
+
total_stakeholders: [...new Set(analyses.flatMap((a) => a.stakeholders)), ...extras],
|
|
271
|
+
overall_risk: manifest.risk_level || "medium",
|
|
272
|
+
},
|
|
273
|
+
additional_requirements: extras,
|
|
274
|
+
dependency_analysis: analyses,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
async function llmSimulation(client, manifest, manifestYaml, profile) {
|
|
278
|
+
const response = await client.messages.create({
|
|
279
|
+
model: "claude-sonnet-4-5-20250929",
|
|
280
|
+
max_tokens: 4096,
|
|
281
|
+
messages: [
|
|
282
|
+
{
|
|
283
|
+
role: "user",
|
|
284
|
+
content: `Enterprise profile: ${profile}\n\nAgent manifest (interf.yaml):\n\`\`\`yaml\n${manifestYaml}\n\`\`\`\n\nProduce the deployment simulation JSON.`,
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
system: SIMULATION_PROMPT,
|
|
288
|
+
});
|
|
289
|
+
const text = response.content.find((b) => b.type === "text");
|
|
290
|
+
if (!text || text.type !== "text")
|
|
291
|
+
throw new Error("No text in LLM response");
|
|
292
|
+
// Extract JSON from response (handle markdown code blocks)
|
|
293
|
+
let jsonStr = text.text.trim();
|
|
294
|
+
const fenceMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
295
|
+
if (fenceMatch)
|
|
296
|
+
jsonStr = fenceMatch[1].trim();
|
|
297
|
+
return JSON.parse(jsonStr);
|
|
298
|
+
}
|
|
299
|
+
export function createServer() {
|
|
300
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
301
|
+
if (!apiKey) {
|
|
302
|
+
console.error("interf-gateway: WARNING — ANTHROPIC_API_KEY not configured. run_simulation will not work.");
|
|
303
|
+
console.error("interf-gateway: Set it via: claude mcp add interf-gateway -e ANTHROPIC_API_KEY=sk-... -- npx -y @interf/gateway");
|
|
304
|
+
}
|
|
305
|
+
const client = apiKey ? new Anthropic({ apiKey }) : null;
|
|
306
|
+
const server = new McpServer({
|
|
307
|
+
name: "interf-gateway",
|
|
308
|
+
version: "0.0.1",
|
|
309
|
+
}, {
|
|
310
|
+
instructions: SERVER_INSTRUCTIONS,
|
|
311
|
+
});
|
|
312
|
+
server.registerTool("get_protocol_guidance", {
|
|
313
|
+
description: "Returns the full Interf Protocol specification, including the interf.yaml schema, " +
|
|
314
|
+
"canonical dependency types, and step-by-step instructions for generating a manifest. " +
|
|
315
|
+
"Call this first before helping a user create their agent readiness spec.",
|
|
316
|
+
inputSchema: {},
|
|
317
|
+
}, async () => ({
|
|
318
|
+
content: [{ type: "text", text: PROTOCOL_GUIDANCE }],
|
|
319
|
+
}));
|
|
320
|
+
server.registerTool("run_simulation", {
|
|
321
|
+
description: "Simulates enterprise deployment of an agent by analyzing its interf.yaml manifest " +
|
|
322
|
+
"against target enterprise profiles. Returns per-dependency timeline estimates, " +
|
|
323
|
+
"stakeholder requirements, risks, and recommendations. " +
|
|
324
|
+
"If ANTHROPIC_API_KEY is configured, uses LLM for rich analysis. Otherwise returns heuristic estimates.",
|
|
325
|
+
inputSchema: {
|
|
326
|
+
manifest: z
|
|
327
|
+
.string()
|
|
328
|
+
.describe("The interf.yaml manifest content as a YAML string"),
|
|
329
|
+
enterprise_profiles: z
|
|
330
|
+
.array(z.string())
|
|
331
|
+
.describe('Target enterprise profiles to simulate against, e.g. ["Fortune 500 bank", "Series B fintech"]'),
|
|
332
|
+
},
|
|
333
|
+
}, async ({ manifest, enterprise_profiles }) => {
|
|
334
|
+
if (!client) {
|
|
335
|
+
return {
|
|
336
|
+
content: [
|
|
337
|
+
{
|
|
338
|
+
type: "text",
|
|
339
|
+
text: "Error: ANTHROPIC_API_KEY not configured. Cannot run simulation.\n\nTo fix, re-add the MCP server with your API key:\n claude mcp add interf-gateway -e ANTHROPIC_API_KEY=sk-... -- npx -y @interf/gateway",
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
let parsed;
|
|
345
|
+
try {
|
|
346
|
+
parsed = YAML.parse(manifest);
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
return {
|
|
350
|
+
content: [
|
|
351
|
+
{
|
|
352
|
+
type: "text",
|
|
353
|
+
text: "Error: Invalid YAML in manifest. Please check the syntax.",
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
if (!parsed.dependencies || parsed.dependencies.length === 0) {
|
|
359
|
+
return {
|
|
360
|
+
content: [
|
|
361
|
+
{
|
|
362
|
+
type: "text",
|
|
363
|
+
text: "Error: Manifest has no dependencies. Add at least one dependency to simulate.",
|
|
364
|
+
},
|
|
365
|
+
],
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
const results = [];
|
|
369
|
+
for (const profile of enterprise_profiles) {
|
|
370
|
+
try {
|
|
371
|
+
const result = await llmSimulation(client, parsed, manifest, profile);
|
|
372
|
+
results.push(result);
|
|
373
|
+
}
|
|
374
|
+
catch (err) {
|
|
375
|
+
console.error(`interf-gateway: LLM simulation failed for "${profile}":`, err);
|
|
376
|
+
return {
|
|
377
|
+
content: [
|
|
378
|
+
{
|
|
379
|
+
type: "text",
|
|
380
|
+
text: `Error: Simulation failed for profile "${profile}". Check ANTHROPIC_API_KEY is valid.`,
|
|
381
|
+
},
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
const output = {
|
|
387
|
+
agent: parsed.name || "unnamed-agent",
|
|
388
|
+
version: parsed.version || "0.0.0",
|
|
389
|
+
simulations: results,
|
|
390
|
+
};
|
|
391
|
+
return {
|
|
392
|
+
content: [
|
|
393
|
+
{
|
|
394
|
+
type: "text",
|
|
395
|
+
text: JSON.stringify(output, null, 2),
|
|
396
|
+
},
|
|
397
|
+
],
|
|
398
|
+
};
|
|
399
|
+
});
|
|
400
|
+
return server;
|
|
401
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@interf/gateway",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Agent Readiness Protocol - MCP server for coding agents to understand enterprise integration requirements",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"interf-gateway": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && chmod 755 dist/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@anthropic-ai/sdk": "^0.74.0",
|
|
17
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
18
|
+
"yaml": "^2.7.1",
|
|
19
|
+
"zod": "^3.24.2"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^22.15.3",
|
|
23
|
+
"typescript": "^5.8.3"
|
|
24
|
+
}
|
|
25
|
+
}
|