opalserve 0.1.1 → 2.0.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.
Files changed (223) hide show
  1. package/README.md +112 -116
  2. package/assets/logo.svg +54 -0
  3. package/dist/cli/commands/health.d.ts +4 -0
  4. package/dist/cli/commands/health.d.ts.map +1 -0
  5. package/dist/cli/commands/health.js +36 -0
  6. package/dist/cli/commands/health.js.map +1 -0
  7. package/dist/cli/commands/init.d.ts +2 -0
  8. package/dist/cli/commands/init.d.ts.map +1 -0
  9. package/dist/cli/commands/init.js +81 -0
  10. package/dist/cli/commands/init.js.map +1 -0
  11. package/dist/cli/commands/server.d.ts +10 -0
  12. package/dist/cli/commands/server.d.ts.map +1 -0
  13. package/dist/cli/commands/server.js +108 -0
  14. package/dist/cli/commands/server.js.map +1 -0
  15. package/dist/cli/commands/start.d.ts +6 -0
  16. package/dist/cli/commands/start.d.ts.map +1 -0
  17. package/dist/cli/commands/start.js +63 -0
  18. package/dist/cli/commands/start.js.map +1 -0
  19. package/dist/cli/commands/status.d.ts +2 -0
  20. package/dist/cli/commands/status.d.ts.map +1 -0
  21. package/dist/cli/commands/status.js +21 -0
  22. package/dist/cli/commands/status.js.map +1 -0
  23. package/dist/cli/commands/tools.d.ts +8 -0
  24. package/dist/cli/commands/tools.d.ts.map +1 -0
  25. package/dist/cli/commands/tools.js +28 -0
  26. package/dist/cli/commands/tools.js.map +1 -0
  27. package/dist/cli/index.d.ts +1 -1
  28. package/dist/cli/index.d.ts.map +1 -1
  29. package/dist/cli/index.js +82 -30
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/ui/banner.d.ts +8 -0
  32. package/dist/cli/ui/banner.d.ts.map +1 -0
  33. package/dist/cli/ui/banner.js +54 -0
  34. package/dist/cli/ui/banner.js.map +1 -0
  35. package/dist/cli/ui/prompts.d.ts +11 -0
  36. package/dist/cli/ui/prompts.d.ts.map +1 -0
  37. package/dist/cli/ui/prompts.js +74 -0
  38. package/dist/cli/ui/prompts.js.map +1 -0
  39. package/dist/cli/ui/table.d.ts +5 -0
  40. package/dist/cli/ui/table.d.ts.map +1 -0
  41. package/dist/cli/ui/table.js +103 -0
  42. package/dist/cli/ui/table.js.map +1 -0
  43. package/dist/config/defaults.d.ts +5 -0
  44. package/dist/config/defaults.d.ts.map +1 -0
  45. package/dist/config/defaults.js +18 -0
  46. package/dist/config/defaults.js.map +1 -0
  47. package/dist/config/loader.d.ts +4 -0
  48. package/dist/config/loader.d.ts.map +1 -0
  49. package/dist/config/loader.js +57 -0
  50. package/dist/config/loader.js.map +1 -0
  51. package/dist/config/schema.d.ts +2 -0
  52. package/dist/config/schema.d.ts.map +1 -0
  53. package/dist/config/schema.js +2 -0
  54. package/dist/config/schema.js.map +1 -0
  55. package/dist/core/discovery.d.ts +17 -0
  56. package/dist/core/discovery.d.ts.map +1 -0
  57. package/dist/core/discovery.js +31 -0
  58. package/dist/core/discovery.js.map +1 -0
  59. package/dist/core/proxy.d.ts +14 -0
  60. package/dist/core/proxy.d.ts.map +1 -0
  61. package/dist/core/proxy.js +36 -0
  62. package/dist/core/proxy.js.map +1 -0
  63. package/dist/core/registry.d.ts +28 -31
  64. package/dist/core/registry.d.ts.map +1 -1
  65. package/dist/core/registry.js +90 -234
  66. package/dist/core/registry.js.map +1 -1
  67. package/dist/core/server-manager.d.ts +18 -0
  68. package/dist/core/server-manager.d.ts.map +1 -0
  69. package/dist/core/server-manager.js +120 -0
  70. package/dist/core/server-manager.js.map +1 -0
  71. package/dist/index.d.ts +11 -12
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +14 -9
  74. package/dist/index.js.map +1 -1
  75. package/dist/server/app.d.ts +8 -0
  76. package/dist/server/app.d.ts.map +1 -0
  77. package/dist/server/app.js +35 -0
  78. package/dist/server/app.js.map +1 -0
  79. package/dist/server/mcp-gateway.d.ts +12 -0
  80. package/dist/server/mcp-gateway.d.ts.map +1 -0
  81. package/dist/server/mcp-gateway.js +91 -0
  82. package/dist/server/mcp-gateway.js.map +1 -0
  83. package/dist/server/routes/health.d.ts +4 -0
  84. package/dist/server/routes/health.d.ts.map +1 -0
  85. package/dist/server/routes/health.js +22 -0
  86. package/dist/server/routes/health.js.map +1 -0
  87. package/dist/server/routes/servers.d.ts +4 -0
  88. package/dist/server/routes/servers.d.ts.map +1 -0
  89. package/dist/server/routes/servers.js +47 -0
  90. package/dist/server/routes/servers.js.map +1 -0
  91. package/dist/server/routes/tools.d.ts +4 -0
  92. package/dist/server/routes/tools.d.ts.map +1 -0
  93. package/dist/server/routes/tools.js +44 -0
  94. package/dist/server/routes/tools.js.map +1 -0
  95. package/dist/storage/database.d.ts +41 -0
  96. package/dist/storage/database.d.ts.map +1 -0
  97. package/dist/storage/database.js +195 -0
  98. package/dist/storage/database.js.map +1 -0
  99. package/dist/storage/repositories/server-repo.d.ts +2 -0
  100. package/dist/storage/repositories/server-repo.d.ts.map +1 -0
  101. package/dist/storage/repositories/server-repo.js +3 -0
  102. package/dist/storage/repositories/server-repo.js.map +1 -0
  103. package/dist/storage/repositories/tool-repo.d.ts +2 -0
  104. package/dist/storage/repositories/tool-repo.d.ts.map +1 -0
  105. package/dist/storage/repositories/tool-repo.js +3 -0
  106. package/dist/storage/repositories/tool-repo.js.map +1 -0
  107. package/dist/types/index.d.ts +384 -591
  108. package/dist/types/index.d.ts.map +1 -1
  109. package/dist/types/index.js +44 -69
  110. package/dist/types/index.js.map +1 -1
  111. package/dist/utils/logger.d.ts +7 -0
  112. package/dist/utils/logger.d.ts.map +1 -0
  113. package/dist/utils/logger.js +23 -0
  114. package/dist/utils/logger.js.map +1 -0
  115. package/package.json +64 -53
  116. package/.env.example +0 -19
  117. package/config/servers.example.yaml +0 -67
  118. package/config/servers.yaml +0 -2
  119. package/dist/cli/discover.d.ts +0 -3
  120. package/dist/cli/discover.d.ts.map +0 -1
  121. package/dist/cli/discover.js +0 -160
  122. package/dist/cli/discover.js.map +0 -1
  123. package/dist/connectors/base.d.ts +0 -49
  124. package/dist/connectors/base.d.ts.map +0 -1
  125. package/dist/connectors/base.js +0 -45
  126. package/dist/connectors/base.js.map +0 -1
  127. package/dist/connectors/custom.d.ts +0 -19
  128. package/dist/connectors/custom.d.ts.map +0 -1
  129. package/dist/connectors/custom.js +0 -129
  130. package/dist/connectors/custom.js.map +0 -1
  131. package/dist/connectors/github.d.ts +0 -18
  132. package/dist/connectors/github.d.ts.map +0 -1
  133. package/dist/connectors/github.js +0 -188
  134. package/dist/connectors/github.js.map +0 -1
  135. package/dist/connectors/google-drive.d.ts +0 -18
  136. package/dist/connectors/google-drive.d.ts.map +0 -1
  137. package/dist/connectors/google-drive.js +0 -209
  138. package/dist/connectors/google-drive.js.map +0 -1
  139. package/dist/connectors/index.d.ts +0 -11
  140. package/dist/connectors/index.d.ts.map +0 -1
  141. package/dist/connectors/index.js +0 -76
  142. package/dist/connectors/index.js.map +0 -1
  143. package/dist/connectors/postgres.d.ts +0 -18
  144. package/dist/connectors/postgres.d.ts.map +0 -1
  145. package/dist/connectors/postgres.js +0 -140
  146. package/dist/connectors/postgres.js.map +0 -1
  147. package/dist/connectors/slack.d.ts +0 -18
  148. package/dist/connectors/slack.d.ts.map +0 -1
  149. package/dist/connectors/slack.js +0 -181
  150. package/dist/connectors/slack.js.map +0 -1
  151. package/dist/core/auth.d.ts +0 -26
  152. package/dist/core/auth.d.ts.map +0 -1
  153. package/dist/core/auth.js +0 -81
  154. package/dist/core/auth.js.map +0 -1
  155. package/dist/core/tokenizer.d.ts +0 -16
  156. package/dist/core/tokenizer.d.ts.map +0 -1
  157. package/dist/core/tokenizer.js +0 -29
  158. package/dist/core/tokenizer.js.map +0 -1
  159. package/dist/governance/audit.d.ts +0 -27
  160. package/dist/governance/audit.d.ts.map +0 -1
  161. package/dist/governance/audit.js +0 -149
  162. package/dist/governance/audit.js.map +0 -1
  163. package/dist/governance/index.d.ts +0 -5
  164. package/dist/governance/index.d.ts.map +0 -1
  165. package/dist/governance/index.js +0 -5
  166. package/dist/governance/index.js.map +0 -1
  167. package/dist/governance/policy.d.ts +0 -20
  168. package/dist/governance/policy.d.ts.map +0 -1
  169. package/dist/governance/policy.js +0 -162
  170. package/dist/governance/policy.js.map +0 -1
  171. package/dist/governance/rate-limiter.d.ts +0 -20
  172. package/dist/governance/rate-limiter.d.ts.map +0 -1
  173. package/dist/governance/rate-limiter.js +0 -73
  174. package/dist/governance/rate-limiter.js.map +0 -1
  175. package/dist/governance/types.d.ts +0 -246
  176. package/dist/governance/types.d.ts.map +0 -1
  177. package/dist/governance/types.js +0 -72
  178. package/dist/governance/types.js.map +0 -1
  179. package/dist/identity/access-control.d.ts +0 -15
  180. package/dist/identity/access-control.d.ts.map +0 -1
  181. package/dist/identity/access-control.js +0 -81
  182. package/dist/identity/access-control.js.map +0 -1
  183. package/dist/identity/index.d.ts +0 -4
  184. package/dist/identity/index.d.ts.map +0 -1
  185. package/dist/identity/index.js +0 -4
  186. package/dist/identity/index.js.map +0 -1
  187. package/dist/identity/manager.d.ts +0 -29
  188. package/dist/identity/manager.d.ts.map +0 -1
  189. package/dist/identity/manager.js +0 -167
  190. package/dist/identity/manager.js.map +0 -1
  191. package/dist/identity/types.d.ts +0 -237
  192. package/dist/identity/types.d.ts.map +0 -1
  193. package/dist/identity/types.js +0 -80
  194. package/dist/identity/types.js.map +0 -1
  195. package/dist/registry/server.d.ts +0 -14
  196. package/dist/registry/server.d.ts.map +0 -1
  197. package/dist/registry/server.js +0 -177
  198. package/dist/registry/server.js.map +0 -1
  199. package/dist/utils/config.d.ts +0 -29
  200. package/dist/utils/config.d.ts.map +0 -1
  201. package/dist/utils/config.js +0 -47
  202. package/dist/utils/config.js.map +0 -1
  203. package/dist/utils/index.d.ts +0 -7
  204. package/dist/utils/index.d.ts.map +0 -1
  205. package/dist/utils/index.js +0 -44
  206. package/dist/utils/index.js.map +0 -1
  207. package/dist/workflow/engine.d.ts +0 -18
  208. package/dist/workflow/engine.d.ts.map +0 -1
  209. package/dist/workflow/engine.js +0 -155
  210. package/dist/workflow/engine.js.map +0 -1
  211. package/dist/workflow/index.d.ts +0 -4
  212. package/dist/workflow/index.d.ts.map +0 -1
  213. package/dist/workflow/index.js +0 -4
  214. package/dist/workflow/index.js.map +0 -1
  215. package/dist/workflow/templates.d.ts +0 -4
  216. package/dist/workflow/templates.d.ts.map +0 -1
  217. package/dist/workflow/templates.js +0 -218
  218. package/dist/workflow/templates.js.map +0 -1
  219. package/dist/workflow/types.d.ts +0 -255
  220. package/dist/workflow/types.d.ts.map +0 -1
  221. package/dist/workflow/types.js +0 -48
  222. package/dist/workflow/types.js.map +0 -1
  223. package/eslint.config.js +0 -25
package/README.md CHANGED
@@ -1,33 +1,28 @@
1
- # OpalServe
1
+ <p align="center">
2
+ <img src="assets/banner.svg" alt="OpalServe" width="800" />
3
+ </p>
2
4
 
3
- > Enterprise-grade MCP (Model Context Protocol) Tool Registry & Discovery Hub for AI Agents
5
+ <p align="center">
6
+ <strong>Local MCP Tool Registry & Discovery Hub</strong>
7
+ </p>
4
8
 
5
- [![npm version](https://img.shields.io/npm/v/opalserve?style=flat-square)](https://www.npmjs.com/package/opalserve)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
7
- [![Node.js](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen?style=flat-square)](https://nodejs.org/)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue?style=flat-square)](https://www.typescriptlang.org/)
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/opalserve"><img src="https://img.shields.io/npm/v/opalserve?style=flat-square&color=F97316" alt="npm version" /></a>
11
+ <a href="https://www.npmjs.com/package/opalserve"><img src="https://img.shields.io/npm/dm/opalserve?style=flat-square" alt="downloads" /></a>
12
+ <a href="https://github.com/adityaidev/opalserve/blob/master/LICENSE"><img src="https://img.shields.io/github/license/adityaidev/opalserve?style=flat-square" alt="license" /></a>
13
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen?style=flat-square" alt="node version" /></a>
14
+ </p>
9
15
 
10
- ## What is OpalServe?
11
-
12
- OpalServe solves the **"N×M" integration problem** in AI agent tooling. Before MCP, developers had to build custom connectors for every combination of AI model and tool. OpalServe provides a centralized registry with intelligent, context-sized tool discovery.
13
-
14
- ### Key Features
15
-
16
- - **Intelligent Discovery**: Context-sized responses with relevance scoring
17
- - **5 Pre-built Connectors**: GitHub, Slack, PostgreSQL, Google Drive, Custom
18
- - **40+ MCP Tools**: Ready-to-use tools with full JSON Schema documentation
19
- - **Visual Workflow Builder**: Build multi-step agentic workflows with templates
20
- - **Enterprise Security**: JWT authentication, RBAC, audit logging
21
- - **Governance**: Policy engine, rate limiting, compliance tracking
16
+ ---
22
17
 
23
- ## Why OpalServe?
18
+ **OpalServe** aggregates, discovers, and proxies tools across multiple MCP (Model Context Protocol) servers from a single hub.
24
19
 
25
- | Problem | Solution |
26
- |---------|----------|
27
- | Context bloat from loading all tools | Intelligent discovery with relevance scoring |
28
- | No standardized auth identity | JWT-based agent identity propagation |
29
- | Security vulnerabilities | Native `fetch` (no axios - March 2026 fix) |
30
- | Complex multi-tool workflows | Visual workflow builder with templates |
20
+ - **Real MCP Protocol** — Connects to any MCP server via stdio, SSE, or Streamable HTTP
21
+ - **Full-Text Search** — SQLite FTS5-powered tool discovery across all servers
22
+ - **Beautiful CLI** Interactive setup, gradient banners, color-coded tables
23
+ - **HTTP API** Fastify REST API for managing servers and tools
24
+ - **Persistent** SQLite database survives restarts
25
+ - **MCP Gateway** Acts as an MCP server itself for LLM clients
31
26
 
32
27
  ## Quick Start
33
28
 
@@ -35,113 +30,114 @@ OpalServe solves the **"N×M" integration problem** in AI agent tooling. Before
35
30
  # Install globally
36
31
  npm install -g opalserve
37
32
 
38
- # Or use via npx
39
- npx opalserve
33
+ # Interactive setup
34
+ opalserve init
35
+
36
+ # Start the registry
37
+ opalserve start
38
+ ```
39
+
40
+ ## Add MCP Servers
41
+
42
+ ```bash
43
+ # Filesystem access
44
+ opalserve server add --name files --stdio "npx -y @modelcontextprotocol/server-filesystem ."
40
45
 
41
- # Start the server
42
- opalserve
46
+ # GitHub
47
+ opalserve server add --name github --stdio "npx -y @modelcontextprotocol/server-github" --env GITHUB_TOKEN=ghp_xxx
43
48
 
44
- # Discover available tools
45
- opalserve-discover "github pull requests"
49
+ # Any MCP server
50
+ opalserve server add --name my-server --url https://mcp.example.com/sse
46
51
  ```
47
52
 
48
- ## Available Tools
49
-
50
- ### GitHub (8 tools)
51
- - List repositories, Get repository details
52
- - List pull requests, Get PR details, Create PR review
53
- - Create issue, List issues, Search code
54
-
55
- ### Slack (8 tools)
56
- - Post message, Get channel info, List channels
57
- - List messages, Update message, Delete message
58
- - Upload file, Search messages
59
-
60
- ### PostgreSQL (6 tools)
61
- - Execute query, Get schema, List tables
62
- - Get table info, List databases, Health check
63
-
64
- ### Google Drive (10 tools)
65
- - List files, Get file, Create folder, Upload file
66
- - Share file, List permissions, Search files
67
- - Delete file, Download file, Get file metadata
68
-
69
- ### Custom (5 tools)
70
- - HTTP request, Webhook trigger, Transform data
71
- - Aggregate data, Route request
72
-
73
- ## API Endpoints
74
-
75
- | Method | Endpoint | Description |
76
- |--------|----------|-------------|
77
- | GET | `/api/v1/health` | Health check |
78
- | GET | `/api/v1/discover?query=<text>` | Discover tools by query |
79
- | GET | `/api/v1/tools` | List all registered tools |
80
- | GET | `/api/v1/tools/:id` | Get specific tool details |
81
- | GET | `/api/v1/servers` | List MCP servers |
82
- | POST | `/api/v1/servers/register` | Register new MCP server |
83
- | POST | `/api/v1/auth/token` | Generate JWT token |
84
-
85
- ## Configuration
86
-
87
- ```env
88
- PORT=3000
89
- HOST=localhost
90
- JWT_SECRET=your-secret-key
91
- GITHUB_TOKEN=ghp_xxx
92
- SLACK_BOT_TOKEN=xoxb-xxx
93
- POSTGRES_URL=postgresql://user:pass@host:5432/db
94
- GOOGLE_SERVICE_ACCOUNT=./config/google-service-account.json
95
- ENABLE_AUTH=false
53
+ ## Discover Tools
54
+
55
+ ```bash
56
+ # List all tools
57
+ opalserve tools list
58
+
59
+ # Full-text search
60
+ opalserve tools search "create issue"
61
+
62
+ # Check server health
63
+ opalserve health
96
64
  ```
97
65
 
98
- ## Architecture
66
+ ## Use as MCP Gateway
99
67
 
68
+ Point your MCP client (Claude Desktop, Cursor, etc.) at OpalServe to access all tools from one connection:
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "opalserve": {
74
+ "command": "npx",
75
+ "args": ["-y", "opalserve", "start", "--mcp"]
76
+ }
77
+ }
78
+ }
100
79
  ```
101
- ┌─────────────────────────────────────────────────────────────┐
102
- │ O P A L S E R V E │
103
- │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐│
104
- │ │ Discovery │ │ Auth & │ │ Tool Registry ││
105
- │ │ Endpoint │──│ RBAC │──│ & Indexing ││
106
- │ └─────────────┘ └─────────────┘ └─────────────────────┘│
107
- └─────────────────────────────────────────────────────────────┘
108
- │ │ │
109
- ▼ ▼ ▼
110
- ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
111
- │ GitHub │ │ Slack │ │ PostgreSQL │
112
- │ Connector │ │ Connector │ │ Connector │
113
- └─────────────┘ └─────────────┘ └─────────────┘
114
- │ │ │
115
- ▼ ▼ ▼
116
- ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
117
- Google Drive│ │ Custom │ │ More... │
118
- │ Connector │ │ Connector │ │ │
119
- └─────────────┘ └─────────────┘ └─────────────┘
80
+
81
+ ## Library Usage
82
+
83
+ ```typescript
84
+ import { OpalServeRegistry } from 'opalserve';
85
+
86
+ const registry = await OpalServeRegistry.create({
87
+ servers: [{
88
+ name: 'my-files',
89
+ transport: { type: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '.'] },
90
+ }],
91
+ });
92
+
93
+ await registry.start();
94
+
95
+ const tools = registry.listTools();
96
+ const results = registry.searchTools('read file');
97
+ const result = await registry.callTool('my-files:read_file', { path: './README.md' });
98
+
99
+ await registry.stop();
120
100
  ```
121
101
 
122
- ## Security Features
102
+ ## HTTP API
123
103
 
124
- - **JWT Authentication**: Secure agent identity propagation
125
- - **RBAC**: Fine-grained permission-based access control
126
- - **Confused Deputy Prevention**: Blocks malicious prompt injection
127
- - **Native HTTP**: Uses Node.js `fetch` (no external dependencies)
128
- - **Audit Logging**: Track all tool invocations and access
104
+ Start the server with `opalserve start`, then:
129
105
 
130
- ## Use Cases
106
+ ```bash
107
+ # Health check
108
+ curl http://localhost:3456/api/v1/health
131
109
 
132
- 1. **AI Agent Tooling**: Give AI agents access to enterprise tools
133
- 2. **Tool Discovery**: Find relevant tools based on natural language queries
134
- 3. **Workflow Automation**: Build multi-step workflows with visual builder
135
- 4. **Governance**: Monitor and control tool usage across organizations
110
+ # List tools
111
+ curl http://localhost:3456/api/v1/tools
136
112
 
137
- ## Contributing
113
+ # Search tools
114
+ curl "http://localhost:3456/api/v1/tools/search?q=read+file"
138
115
 
139
- Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
116
+ # Call a tool
117
+ curl -X POST http://localhost:3456/api/v1/tools/files%3Aread_file/call \
118
+ -H "Content-Type: application/json" \
119
+ -d '{"path": "./README.md"}'
120
+ ```
140
121
 
141
- ## License
122
+ ## Architecture
142
123
 
143
- MIT License - see [LICENSE](LICENSE) for details.
124
+ ```
125
+ [Claude/Cursor] <--MCP--> [OpalServe Gateway] <--MCP--> [Server A]
126
+ | <--MCP--> [Server B]
127
+ [HTTP API] <--MCP--> [Server C]
128
+ [SQLite DB]
129
+ ```
144
130
 
145
- ---
131
+ OpalServe is simultaneously:
132
+ - An **MCP Client** to each backend server
133
+ - An **MCP Server** exposing aggregated tools
134
+ - An **HTTP API** for management
135
+ - A **CLI** for humans
136
+
137
+ ## Documentation
138
+
139
+ Full documentation at [adityaidev.github.io/opalserve](https://adityaidev.github.io/opalserve)
140
+
141
+ ## License
146
142
 
147
- **Built for the AI Agent era** - Enterprise-ready MCP tool registry
143
+ MIT
@@ -0,0 +1,54 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="none">
2
+ <defs>
3
+ <linearGradient id="opal-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" stop-color="#F59E0B"/>
5
+ <stop offset="35%" stop-color="#F97316"/>
6
+ <stop offset="65%" stop-color="#EF4444"/>
7
+ <stop offset="100%" stop-color="#8B5CF6"/>
8
+ </linearGradient>
9
+ <linearGradient id="opal-shine" x1="20%" y1="0%" x2="80%" y2="100%">
10
+ <stop offset="0%" stop-color="#FFFFFF" stop-opacity="0.4"/>
11
+ <stop offset="50%" stop-color="#FFFFFF" stop-opacity="0.1"/>
12
+ <stop offset="100%" stop-color="#FFFFFF" stop-opacity="0"/>
13
+ </linearGradient>
14
+ <linearGradient id="facet-light" x1="0%" y1="0%" x2="100%" y2="100%">
15
+ <stop offset="0%" stop-color="#FFFFFF" stop-opacity="0.25"/>
16
+ <stop offset="100%" stop-color="#FFFFFF" stop-opacity="0.05"/>
17
+ </linearGradient>
18
+ </defs>
19
+
20
+ <!-- Outer gem shape — hexagonal prism -->
21
+ <polygon
22
+ points="256,32 432,128 432,320 256,480 80,320 80,128"
23
+ fill="url(#opal-gradient)"
24
+ />
25
+
26
+ <!-- Top facet highlight -->
27
+ <polygon
28
+ points="256,32 432,128 256,192 80,128"
29
+ fill="url(#opal-shine)"
30
+ />
31
+
32
+ <!-- Left facet -->
33
+ <polygon
34
+ points="80,128 256,192 256,380 80,320"
35
+ fill="url(#facet-light)"
36
+ opacity="0.3"
37
+ />
38
+
39
+ <!-- Inner refraction lines -->
40
+ <line x1="256" y1="192" x2="256" y2="380" stroke="#FFFFFF" stroke-opacity="0.15" stroke-width="2"/>
41
+ <line x1="256" y1="192" x2="160" y2="260" stroke="#FFFFFF" stroke-opacity="0.12" stroke-width="1.5"/>
42
+ <line x1="256" y1="192" x2="352" y2="260" stroke="#FFFFFF" stroke-opacity="0.12" stroke-width="1.5"/>
43
+ <line x1="256" y1="192" x2="180" y2="340" stroke="#FFFFFF" stroke-opacity="0.08" stroke-width="1"/>
44
+ <line x1="256" y1="192" x2="332" y2="340" stroke="#FFFFFF" stroke-opacity="0.08" stroke-width="1"/>
45
+
46
+ <!-- Center sparkle -->
47
+ <circle cx="256" cy="220" r="6" fill="#FFFFFF" opacity="0.6"/>
48
+ <circle cx="256" cy="220" r="12" fill="#FFFFFF" opacity="0.15"/>
49
+
50
+ <!-- Small accent sparkles -->
51
+ <circle cx="200" cy="260" r="3" fill="#FFFFFF" opacity="0.3"/>
52
+ <circle cx="310" cy="280" r="2.5" fill="#FFFFFF" opacity="0.25"/>
53
+ <circle cx="240" cy="320" r="2" fill="#FFFFFF" opacity="0.2"/>
54
+ </svg>
@@ -0,0 +1,4 @@
1
+ export declare function healthCommand(options: {
2
+ server?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/health.ts"],"names":[],"mappings":"AAKA,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC/E"}
@@ -0,0 +1,36 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { OpalServeRegistry } from '../../core/registry.js';
4
+ import { showMiniBanner, showSuccess, showError } from '../ui/banner.js';
5
+ export async function healthCommand(options) {
6
+ showMiniBanner();
7
+ const spinner = ora('Running health checks...').start();
8
+ const registry = await OpalServeRegistry.create();
9
+ // Reconnect servers to get fresh status
10
+ const servers = registry.config.servers.filter(s => s.enabled);
11
+ if (options.server) {
12
+ const filtered = servers.filter(s => s.name === options.server);
13
+ if (filtered.length === 0) {
14
+ spinner.fail(`Server "${options.server}" not found`);
15
+ registry.getDatabase().close();
16
+ return;
17
+ }
18
+ }
19
+ const results = await registry.healthCheck(options.server);
20
+ spinner.stop();
21
+ console.log(` ${chalk.bold('Health Check Results')}\n`);
22
+ for (const result of results) {
23
+ if (result.healthy) {
24
+ showSuccess(`${chalk.white(result.serverName)} — ${chalk.green('healthy')} (${result.toolCount} tools)`);
25
+ }
26
+ else {
27
+ showError(`${chalk.white(result.serverName)} — ${chalk.red('unhealthy')}${result.error ? ` (${result.error})` : ''}`);
28
+ }
29
+ }
30
+ if (results.length === 0) {
31
+ console.log(chalk.gray(' No servers registered.'));
32
+ }
33
+ console.log('');
34
+ registry.getDatabase().close();
35
+ }
36
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/cli/commands/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA4B;IAC9D,cAAc,EAAE,CAAC;IAEjB,MAAM,OAAO,GAAG,GAAG,CAAC,0BAA0B,CAAC,CAAC,KAAK,EAAE,CAAC;IAExD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,CAAC;IAElD,wCAAwC;IACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC/D,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QAChE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC;YACrD,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO,CAAC,IAAI,EAAE,CAAC;IAEf,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAEzD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,WAAW,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,SAAS,SAAS,CAAC,CAAC;QAC3G,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxH,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function initCommand(): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAQA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAyDjD"}
@@ -0,0 +1,81 @@
1
+ import { writeFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import chalk from 'chalk';
4
+ import { select } from '@inquirer/prompts';
5
+ import { showBox, showSuccess, showInfo } from '../ui/banner.js';
6
+ import { promptServerName, promptTransportType, promptStdioCommand, promptUrl, promptEnvVars, promptConfirm, promptPort } from '../ui/prompts.js';
7
+ export async function initCommand() {
8
+ showBox(`Welcome to ${chalk.bold('OpalServe')} Setup\n\n` +
9
+ 'This wizard will help you configure OpalServe\n' +
10
+ 'as your local MCP tool registry.', 'Setup');
11
+ // Step 1: Config location
12
+ const configLocation = await select({
13
+ message: 'Where should OpalServe store its configuration?',
14
+ choices: [
15
+ { value: 'local', name: 'Current directory (./opalserve.config.json)' },
16
+ { value: 'home', name: 'Home directory (~/.opalserve/config.json)' },
17
+ ],
18
+ });
19
+ // Step 2: Port
20
+ const port = await promptPort();
21
+ // Step 3: Add servers
22
+ const servers = [];
23
+ let addServer = await promptConfirm('Would you like to register an MCP server now?');
24
+ while (addServer) {
25
+ const server = await promptServerConfig();
26
+ servers.push(server);
27
+ showSuccess(`Server "${server.name}" configured`);
28
+ addServer = await promptConfirm('Add another server?', false);
29
+ }
30
+ // Step 4: Write config
31
+ const config = {
32
+ servers,
33
+ gateway: { port, host: '127.0.0.1' },
34
+ storage: { path: '' },
35
+ logging: { level: 'info' },
36
+ };
37
+ const configPath = configLocation === 'local'
38
+ ? resolve(process.cwd(), 'opalserve.config.json')
39
+ : resolve(process.env.HOME || process.env.USERPROFILE || '.', '.opalserve', 'config.json');
40
+ // Ensure directory exists
41
+ const { mkdirSync } = await import('node:fs');
42
+ const { dirname } = await import('node:path');
43
+ mkdirSync(dirname(configPath), { recursive: true });
44
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
45
+ showSuccess(`Configuration saved to ${chalk.cyan(configPath)}`);
46
+ console.log('');
47
+ showInfo('Next steps:');
48
+ console.log(` ${chalk.cyan('opalserve start')} Start the registry`);
49
+ console.log(` ${chalk.cyan('opalserve server add')} Add more servers`);
50
+ console.log(` ${chalk.cyan('opalserve tools')} Browse available tools`);
51
+ console.log('');
52
+ }
53
+ async function promptServerConfig() {
54
+ const name = await promptServerName();
55
+ const transportType = await promptTransportType();
56
+ if (transportType === 'stdio') {
57
+ const { command, args } = await promptStdioCommand();
58
+ const env = await promptEnvVars();
59
+ return {
60
+ name,
61
+ transport: {
62
+ type: 'stdio',
63
+ command,
64
+ args,
65
+ ...(Object.keys(env).length > 0 ? { env } : {}),
66
+ },
67
+ enabled: true,
68
+ tags: [],
69
+ autoConnect: true,
70
+ };
71
+ }
72
+ const url = await promptUrl();
73
+ return {
74
+ name,
75
+ transport: { type: transportType, url },
76
+ enabled: true,
77
+ tags: [],
78
+ autoConnect: true,
79
+ };
80
+ }
81
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare function serverListCommand(): Promise<void>;
2
+ export declare function serverAddCommand(options: {
3
+ name?: string;
4
+ stdio?: string;
5
+ url?: string;
6
+ transport?: string;
7
+ env?: string[];
8
+ }): Promise<void>;
9
+ export declare function serverRemoveCommand(name: string): Promise<void>;
10
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/server.ts"],"names":[],"mappings":"AAQA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAWvD;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EhB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBrE"}
@@ -0,0 +1,108 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { OpalServeRegistry } from '../../core/registry.js';
4
+ import { McpServerConfigSchema } from '../../types/index.js';
5
+ import { showMiniBanner, showSuccess, showError } from '../ui/banner.js';
6
+ import { renderServerTable } from '../ui/table.js';
7
+ import { promptServerName, promptTransportType, promptStdioCommand, promptUrl, promptEnvVars, promptConfirm } from '../ui/prompts.js';
8
+ export async function serverListCommand() {
9
+ showMiniBanner();
10
+ const registry = await OpalServeRegistry.create();
11
+ const servers = registry.listServers();
12
+ console.log(` ${chalk.bold('Registered Servers')} ${chalk.dim(`(${servers.length})`)}\n`);
13
+ console.log(renderServerTable(servers));
14
+ console.log('');
15
+ registry.getDatabase().close();
16
+ }
17
+ export async function serverAddCommand(options) {
18
+ showMiniBanner();
19
+ let config;
20
+ if (options.name && (options.stdio || options.url)) {
21
+ // Non-interactive mode
22
+ if (options.stdio) {
23
+ const parts = options.stdio.split(/\s+/);
24
+ const envObj = {};
25
+ if (options.env) {
26
+ for (const e of options.env) {
27
+ const [key, ...valueParts] = e.split('=');
28
+ envObj[key] = valueParts.join('=');
29
+ }
30
+ }
31
+ config = McpServerConfigSchema.parse({
32
+ name: options.name,
33
+ transport: {
34
+ type: 'stdio',
35
+ command: parts[0],
36
+ args: parts.slice(1),
37
+ ...(Object.keys(envObj).length > 0 ? { env: envObj } : {}),
38
+ },
39
+ });
40
+ }
41
+ else {
42
+ config = McpServerConfigSchema.parse({
43
+ name: options.name,
44
+ transport: {
45
+ type: options.transport || 'sse',
46
+ url: options.url,
47
+ },
48
+ });
49
+ }
50
+ }
51
+ else {
52
+ // Interactive mode
53
+ const name = options.name || await promptServerName();
54
+ const transportType = await promptTransportType();
55
+ if (transportType === 'stdio') {
56
+ const { command, args } = await promptStdioCommand();
57
+ const env = await promptEnvVars();
58
+ config = McpServerConfigSchema.parse({
59
+ name,
60
+ transport: {
61
+ type: 'stdio',
62
+ command,
63
+ args,
64
+ ...(Object.keys(env).length > 0 ? { env } : {}),
65
+ },
66
+ });
67
+ }
68
+ else {
69
+ const url = await promptUrl();
70
+ config = McpServerConfigSchema.parse({
71
+ name,
72
+ transport: { type: transportType, url },
73
+ });
74
+ }
75
+ }
76
+ const spinner = ora(`Connecting to ${config.name}...`).start();
77
+ try {
78
+ const registry = await OpalServeRegistry.create();
79
+ await registry.addServer(config);
80
+ const server = registry.listServers().find(s => s.name === config.name);
81
+ spinner.succeed(`Connected to ${chalk.white(config.name)}`);
82
+ showSuccess(`${server?.toolCount || 0} tools discovered`);
83
+ registry.getDatabase().close();
84
+ }
85
+ catch (error) {
86
+ spinner.fail(`Failed to connect to ${config.name}`);
87
+ showError(error instanceof Error ? error.message : String(error));
88
+ process.exit(1);
89
+ }
90
+ }
91
+ export async function serverRemoveCommand(name) {
92
+ showMiniBanner();
93
+ const confirmed = await promptConfirm(`Remove server "${name}"?`);
94
+ if (!confirmed) {
95
+ console.log(chalk.dim(' Cancelled'));
96
+ return;
97
+ }
98
+ const registry = await OpalServeRegistry.create();
99
+ try {
100
+ await registry.removeServer(name);
101
+ showSuccess(`Server "${name}" removed`);
102
+ }
103
+ catch (error) {
104
+ showError(error instanceof Error ? error.message : String(error));
105
+ }
106
+ registry.getDatabase().close();
107
+ }
108
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/cli/commands/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function startCommand(options: {
2
+ port?: string;
3
+ host?: string;
4
+ config?: string;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAMA,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgE5G"}