Skip to content

Commit 91564df

Browse files
committed
feat: publish to MCP Registry + fix TypeScript build
- Add mcpName field for MCP Registry publishing - Add server.json for official MCP Registry - Fix TypeScript strict mode errors in mcp-server.ts - Fix test-mcp.ts spawn reliability (node --import tsx) - Add tsx as devDependency - Bump version to 0.5.11
1 parent b27928e commit 91564df

File tree

4 files changed

+67
-8
lines changed

4 files changed

+67
-8
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "shellward",
3-
"version": "0.5.10",
3+
"version": "0.5.11",
4+
"mcpName": "io.github.jnMetaCode/shellward",
45
"description": "AI agent security & MCP security middleware — prompt injection detection, AI firewall, runtime guardrails & data-loss prevention for LLM tool calls. 8-layer defense against data exfiltration & dangerous commands. Zero dependencies. SDK + OpenClaw plugin. Supports LangChain, AutoGPT, Claude Code, Cursor, OpenAI Agents.",
56
"keywords": [
67
"shellward",
@@ -80,6 +81,7 @@
8081
},
8182
"devDependencies": {
8283
"@types/node": "^25.5.0",
84+
"tsx": "^4.21.0",
8385
"typescript": "^5.9.3"
8486
}
8587
}

server.json

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3+
"name": "io.github.jnMetaCode/shellward",
4+
"description": "AI agent security: 7 MCP tools for injection detection, PII scanning, command safety, DLP.",
5+
"repository": {
6+
"url": "https://github.com/jnMetaCode/shellward",
7+
"source": "github"
8+
},
9+
"version": "0.5.11",
10+
"packages": [
11+
{
12+
"registryType": "npm",
13+
"identifier": "shellward",
14+
"version": "0.5.11",
15+
"transport": {
16+
"type": "stdio"
17+
},
18+
"environmentVariables": [
19+
{
20+
"description": "Security mode: enforce (block + log) or audit (log only)",
21+
"isRequired": false,
22+
"format": "string",
23+
"isSecret": false,
24+
"name": "SHELLWARD_MODE"
25+
},
26+
{
27+
"description": "Locale: auto, zh, or en",
28+
"isRequired": false,
29+
"format": "string",
30+
"isSecret": false,
31+
"name": "SHELLWARD_LOCALE"
32+
},
33+
{
34+
"description": "Injection detection threshold 0-100 (lower = stricter)",
35+
"isRequired": false,
36+
"format": "string",
37+
"isSecret": false,
38+
"name": "SHELLWARD_THRESHOLD"
39+
}
40+
]
41+
}
42+
]
43+
}

src/mcp-server.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// }
1818
// }
1919

20-
import { ShellWard } from './core/engine'
20+
import { ShellWard } from './core/engine.js'
2121
import { readFileSync } from 'fs'
2222
import { fileURLToPath } from 'url'
2323
import { dirname, join } from 'path'
@@ -162,7 +162,7 @@ function executeTool(name: string, args: Record<string, unknown>): unknown {
162162
safe: result.safe,
163163
score: result.score,
164164
threshold: result.threshold,
165-
matched_rules: result.matched.map(m => ({
165+
matched_rules: result.matched.map((m: any) => ({
166166
id: m.id,
167167
name: m.name,
168168
score: m.score,
@@ -175,7 +175,7 @@ function executeTool(name: string, args: Record<string, unknown>): unknown {
175175
const result = guard.scanData(String(args.text || ''))
176176
return {
177177
has_sensitive_data: result.hasSensitiveData,
178-
findings: result.findings.map(f => ({
178+
findings: result.findings.map((f: any) => ({
179179
type: f.id,
180180
name: f.name,
181181
count: f.count,

test-mcp.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,25 @@ const tests: TestCase[] = [
108108
]
109109

110110
async function runTests() {
111-
const child = spawn('npx', ['tsx', 'src/mcp-server.ts'], {
111+
const cwd = import.meta.dirname || process.cwd()
112+
const child = spawn('node', ['--import', 'tsx', 'src/mcp-server.ts'], {
112113
stdio: ['pipe', 'pipe', 'pipe'],
113-
cwd: import.meta.dirname,
114+
cwd,
114115
})
115116

116117
const responses = new Map<number, any>()
117118
let buf = Buffer.alloc(0)
118119

120+
child.stderr.on('data', (chunk: Buffer) => {
121+
process.stderr.write(chunk)
122+
})
123+
124+
child.on('exit', (code, sig) => {
125+
if (code !== null && code !== 0) {
126+
console.error(` Server exited with code ${code}`)
127+
}
128+
})
129+
119130
child.stdout.on('data', (chunk: Buffer) => {
120131
buf = Buffer.concat([buf, chunk])
121132

@@ -144,14 +155,17 @@ async function runTests() {
144155
child.stdin.write(Buffer.concat([header, body]))
145156
}
146157

158+
// Wait for server to start
159+
await new Promise(r => setTimeout(r, 2000))
160+
147161
// Send all test requests with small delays
148162
for (const t of tests) {
149163
sendMsg(t.id, t.request.method, t.request.params as any)
150-
await new Promise(r => setTimeout(r, 100))
164+
await new Promise(r => setTimeout(r, 150))
151165
}
152166

153167
// Wait for all responses
154-
await new Promise(r => setTimeout(r, 2000))
168+
await new Promise(r => setTimeout(r, 3000))
155169

156170
child.stdin.end()
157171
child.kill()

0 commit comments

Comments
 (0)