@foundation0/api 1.1.12 → 1.1.13
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 +128 -128
- package/agents.ts +918 -918
- package/git.ts +20 -20
- package/libs/curl.ts +770 -770
- package/mcp/cli.mjs +37 -37
- package/mcp/cli.ts +87 -87
- package/mcp/client.ts +565 -565
- package/mcp/index.ts +15 -15
- package/mcp/server.ts +2991 -2991
- package/net.ts +170 -170
- package/package.json +13 -9
- package/projects.ts +4250 -4340
- package/taskgraph-parser.ts +217 -217
- package/libs/curl.test.ts +0 -130
- package/mcp/AGENTS.md +0 -130
- package/mcp/client.test.ts +0 -142
- package/mcp/manual.md +0 -179
- package/mcp/server.test.ts +0 -967
package/mcp/cli.mjs
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawnSync } from 'node:child_process'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
import { fileURLToPath } from 'node:url'
|
|
5
|
-
|
|
6
|
-
const cliPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'cli.ts')
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
const result = spawnSync(
|
|
10
|
-
'bun',
|
|
11
|
-
['run', cliPath, ...process.argv.slice(2)],
|
|
12
|
-
{
|
|
13
|
-
stdio: 'inherit',
|
|
14
|
-
},
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
if (result.error) {
|
|
18
|
-
throw result.error
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const code = result.status
|
|
22
|
-
if (typeof code === 'number') {
|
|
23
|
-
process.exit(code)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
process.exit(0)
|
|
27
|
-
} catch (error) {
|
|
28
|
-
const typedError = error instanceof Object ? error : null
|
|
29
|
-
const errno = typedError && 'code' in typedError ? typedError.code : undefined
|
|
30
|
-
if (errno === 'ENOENT') {
|
|
31
|
-
console.error('Bun is required to run f0-mcp. Install it and retry: https://bun.sh/docs/installation')
|
|
32
|
-
process.exit(1)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
console.error('Failed to launch f0-mcp server', error)
|
|
36
|
-
process.exit(1)
|
|
37
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
|
|
6
|
+
const cliPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'cli.ts')
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const result = spawnSync(
|
|
10
|
+
'bun',
|
|
11
|
+
['run', cliPath, ...process.argv.slice(2)],
|
|
12
|
+
{
|
|
13
|
+
stdio: 'inherit',
|
|
14
|
+
},
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
if (result.error) {
|
|
18
|
+
throw result.error
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const code = result.status
|
|
22
|
+
if (typeof code === 'number') {
|
|
23
|
+
process.exit(code)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
process.exit(0)
|
|
27
|
+
} catch (error) {
|
|
28
|
+
const typedError = error instanceof Object ? error : null
|
|
29
|
+
const errno = typedError && 'code' in typedError ? typedError.code : undefined
|
|
30
|
+
if (errno === 'ENOENT') {
|
|
31
|
+
console.error('Bun is required to run f0-mcp. Install it and retry: https://bun.sh/docs/installation')
|
|
32
|
+
process.exit(1)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.error('Failed to launch f0-mcp server', error)
|
|
36
|
+
process.exit(1)
|
|
37
|
+
}
|
package/mcp/cli.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { runExampleMcpServer } from './server'
|
|
1
|
+
import { runExampleMcpServer } from './server'
|
|
2
2
|
|
|
3
3
|
const getArgValue = (name: string, fallback?: string): string | undefined => {
|
|
4
4
|
const exactArg = process.argv.find((arg) => arg.startsWith(`${name}=`))
|
|
@@ -18,89 +18,89 @@ const getArgValue = (name: string, fallback?: string): string | undefined => {
|
|
|
18
18
|
return fallback
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const hasFlag = (name: string): boolean => process.argv.includes(name)
|
|
22
|
-
const parseBooleanLiteral = (value: string | undefined): boolean | undefined => {
|
|
23
|
-
if (value === undefined) return undefined
|
|
24
|
-
const normalized = value.trim().toLowerCase()
|
|
25
|
-
if (normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on') {
|
|
26
|
-
return true
|
|
27
|
-
}
|
|
28
|
-
if (normalized === '0' || normalized === 'false' || normalized === 'no' || normalized === 'off') {
|
|
29
|
-
return false
|
|
30
|
-
}
|
|
31
|
-
return undefined
|
|
32
|
-
}
|
|
33
|
-
const resolveBooleanFlag = (name: string, envValue: string | undefined): boolean => {
|
|
34
|
-
const index = process.argv.indexOf(name)
|
|
35
|
-
if (index >= 0) {
|
|
36
|
-
const next = process.argv[index + 1]
|
|
37
|
-
if (!next || next.startsWith('--')) {
|
|
38
|
-
return true
|
|
39
|
-
}
|
|
40
|
-
const parsedNext = parseBooleanLiteral(next)
|
|
41
|
-
if (parsedNext === undefined) {
|
|
42
|
-
throw new Error(`Invalid boolean value for ${name}: ${next}`)
|
|
43
|
-
}
|
|
44
|
-
return parsedNext
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const exactArg = process.argv.find((arg) => arg.startsWith(`${name}=`))
|
|
48
|
-
if (exactArg) {
|
|
49
|
-
const [, raw] = exactArg.split('=', 2)
|
|
50
|
-
const parsed = parseBooleanLiteral(raw)
|
|
51
|
-
if (parsed === undefined) {
|
|
52
|
-
throw new Error(`Invalid boolean value for ${name}: ${raw}`)
|
|
53
|
-
}
|
|
54
|
-
return parsed
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return parseBooleanLiteral(envValue) ?? false
|
|
58
|
-
}
|
|
59
|
-
const parseListArg = (value: string | undefined): string[] => {
|
|
60
|
-
if (!value) return []
|
|
61
|
-
return value
|
|
62
|
-
.split(',')
|
|
63
|
-
.map((entry) => entry.trim())
|
|
64
|
-
.filter((entry) => entry.length > 0)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const serverName = getArgValue('--server-name', 'f0-mcp')
|
|
68
|
-
const serverVersion = getArgValue('--server-version', '1.0.0')
|
|
69
|
-
const toolsPrefix = getArgValue('--tools-prefix') ?? process.env.MCP_TOOLS_PREFIX
|
|
70
|
-
const allowedRootEndpoints = parseListArg(
|
|
71
|
-
getArgValue('--allowed-root-endpoints') ?? process.env.MCP_ALLOWED_ROOT_ENDPOINTS,
|
|
72
|
-
)
|
|
73
|
-
const disableWrite = resolveBooleanFlag('--disable-write', process.env.MCP_DISABLE_WRITE)
|
|
74
|
-
const enableIssues = resolveBooleanFlag('--enable-issues', process.env.MCP_ENABLE_ISSUES)
|
|
75
|
-
const admin = resolveBooleanFlag('--admin', process.env.MCP_ADMIN)
|
|
76
|
-
|
|
77
|
-
if (hasFlag('--help') || hasFlag('-h')) {
|
|
78
|
-
console.log('Usage: f0-mcp [--tools-prefix=api]')
|
|
79
|
-
console.log('Optional flags:')
|
|
80
|
-
console.log(' --server-name <name>')
|
|
81
|
-
console.log(' --server-version <version>')
|
|
82
|
-
console.log(' --tools-prefix <prefix>')
|
|
83
|
-
console.log(' --allowed-root-endpoints <csv>')
|
|
84
|
-
console.log(' Example: --allowed-root-endpoints projects')
|
|
85
|
-
console.log(' Example: --allowed-root-endpoints agents,projects')
|
|
86
|
-
console.log(' --disable-write')
|
|
87
|
-
console.log(' Expose read-only tools and disable write-capable endpoints.')
|
|
88
|
-
console.log(' --enable-issues')
|
|
89
|
-
console.log(' With --disable-write, re-enable issue read/write endpoints.')
|
|
90
|
-
console.log(' --admin')
|
|
91
|
-
console.log(' Expose admin-only destructive endpoints (syncTasks, clearIssues).')
|
|
92
|
-
process.exit(0)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
void runExampleMcpServer({
|
|
96
|
-
serverName: serverName ?? undefined,
|
|
97
|
-
serverVersion: serverVersion ?? undefined,
|
|
98
|
-
toolsPrefix,
|
|
99
|
-
allowedRootEndpoints,
|
|
100
|
-
disableWrite,
|
|
101
|
-
enableIssues,
|
|
102
|
-
admin,
|
|
103
|
-
}).catch((error) => {
|
|
104
|
-
console.error('Failed to start f0-mcp server', error)
|
|
105
|
-
process.exit(1)
|
|
106
|
-
})
|
|
21
|
+
const hasFlag = (name: string): boolean => process.argv.includes(name)
|
|
22
|
+
const parseBooleanLiteral = (value: string | undefined): boolean | undefined => {
|
|
23
|
+
if (value === undefined) return undefined
|
|
24
|
+
const normalized = value.trim().toLowerCase()
|
|
25
|
+
if (normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on') {
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
if (normalized === '0' || normalized === 'false' || normalized === 'no' || normalized === 'off') {
|
|
29
|
+
return false
|
|
30
|
+
}
|
|
31
|
+
return undefined
|
|
32
|
+
}
|
|
33
|
+
const resolveBooleanFlag = (name: string, envValue: string | undefined): boolean => {
|
|
34
|
+
const index = process.argv.indexOf(name)
|
|
35
|
+
if (index >= 0) {
|
|
36
|
+
const next = process.argv[index + 1]
|
|
37
|
+
if (!next || next.startsWith('--')) {
|
|
38
|
+
return true
|
|
39
|
+
}
|
|
40
|
+
const parsedNext = parseBooleanLiteral(next)
|
|
41
|
+
if (parsedNext === undefined) {
|
|
42
|
+
throw new Error(`Invalid boolean value for ${name}: ${next}`)
|
|
43
|
+
}
|
|
44
|
+
return parsedNext
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const exactArg = process.argv.find((arg) => arg.startsWith(`${name}=`))
|
|
48
|
+
if (exactArg) {
|
|
49
|
+
const [, raw] = exactArg.split('=', 2)
|
|
50
|
+
const parsed = parseBooleanLiteral(raw)
|
|
51
|
+
if (parsed === undefined) {
|
|
52
|
+
throw new Error(`Invalid boolean value for ${name}: ${raw}`)
|
|
53
|
+
}
|
|
54
|
+
return parsed
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return parseBooleanLiteral(envValue) ?? false
|
|
58
|
+
}
|
|
59
|
+
const parseListArg = (value: string | undefined): string[] => {
|
|
60
|
+
if (!value) return []
|
|
61
|
+
return value
|
|
62
|
+
.split(',')
|
|
63
|
+
.map((entry) => entry.trim())
|
|
64
|
+
.filter((entry) => entry.length > 0)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const serverName = getArgValue('--server-name', 'f0-mcp')
|
|
68
|
+
const serverVersion = getArgValue('--server-version', '1.0.0')
|
|
69
|
+
const toolsPrefix = getArgValue('--tools-prefix') ?? process.env.MCP_TOOLS_PREFIX
|
|
70
|
+
const allowedRootEndpoints = parseListArg(
|
|
71
|
+
getArgValue('--allowed-root-endpoints') ?? process.env.MCP_ALLOWED_ROOT_ENDPOINTS,
|
|
72
|
+
)
|
|
73
|
+
const disableWrite = resolveBooleanFlag('--disable-write', process.env.MCP_DISABLE_WRITE)
|
|
74
|
+
const enableIssues = resolveBooleanFlag('--enable-issues', process.env.MCP_ENABLE_ISSUES)
|
|
75
|
+
const admin = resolveBooleanFlag('--admin', process.env.MCP_ADMIN)
|
|
76
|
+
|
|
77
|
+
if (hasFlag('--help') || hasFlag('-h')) {
|
|
78
|
+
console.log('Usage: f0-mcp [--tools-prefix=api]')
|
|
79
|
+
console.log('Optional flags:')
|
|
80
|
+
console.log(' --server-name <name>')
|
|
81
|
+
console.log(' --server-version <version>')
|
|
82
|
+
console.log(' --tools-prefix <prefix>')
|
|
83
|
+
console.log(' --allowed-root-endpoints <csv>')
|
|
84
|
+
console.log(' Example: --allowed-root-endpoints projects')
|
|
85
|
+
console.log(' Example: --allowed-root-endpoints agents,projects')
|
|
86
|
+
console.log(' --disable-write')
|
|
87
|
+
console.log(' Expose read-only tools and disable write-capable endpoints.')
|
|
88
|
+
console.log(' --enable-issues')
|
|
89
|
+
console.log(' With --disable-write, re-enable issue read/write endpoints.')
|
|
90
|
+
console.log(' --admin')
|
|
91
|
+
console.log(' Expose admin-only destructive endpoints (syncTasks, clearIssues).')
|
|
92
|
+
process.exit(0)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void runExampleMcpServer({
|
|
96
|
+
serverName: serverName ?? undefined,
|
|
97
|
+
serverVersion: serverVersion ?? undefined,
|
|
98
|
+
toolsPrefix,
|
|
99
|
+
allowedRootEndpoints,
|
|
100
|
+
disableWrite,
|
|
101
|
+
enableIssues,
|
|
102
|
+
admin,
|
|
103
|
+
}).catch((error) => {
|
|
104
|
+
console.error('Failed to start f0-mcp server', error)
|
|
105
|
+
process.exit(1)
|
|
106
|
+
})
|