coreforged-mcp 0.1.0__tar.gz
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.
- coreforged_mcp-0.1.0/LICENSE +21 -0
- coreforged_mcp-0.1.0/PKG-INFO +223 -0
- coreforged_mcp-0.1.0/README.md +191 -0
- coreforged_mcp-0.1.0/pyproject.toml +51 -0
- coreforged_mcp-0.1.0/setup.cfg +4 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/__init__.py +3 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/cli.py +148 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/gateway.py +414 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/loadouts.json +12 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/plugins/_template/plugin.json +10 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/plugins/_template/server.py +28 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/plugins/keyring/__init__.py +0 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/plugins/keyring/adapters/__init__.py +0 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/plugins/keyring/permissions.json +3 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/plugins/keyring/plugin.json +11 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/plugins/keyring/secret_manifest.json +4 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp/plugins/keyring/server.py +244 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp.egg-info/PKG-INFO +223 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp.egg-info/SOURCES.txt +21 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp.egg-info/dependency_links.txt +1 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp.egg-info/entry_points.txt +2 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp.egg-info/requires.txt +11 -0
- coreforged_mcp-0.1.0/src/coreforged_mcp.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CoreForged LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: coreforged-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP gateway that docks multiple servers behind one endpoint with named loadout profiles
|
|
5
|
+
Author-email: CoreForged LLC <corporate@coreforged.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://coreforged.com/products/coreforged-mcp
|
|
8
|
+
Project-URL: Repository, https://github.com/coreforged/coreforged-mcp
|
|
9
|
+
Project-URL: Documentation, https://github.com/coreforged/coreforged-mcp#readme
|
|
10
|
+
Keywords: mcp,claude,ai,gateway,plugins
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: mcp[cli]<2,>=1.0.0
|
|
24
|
+
Provides-Extra: keyring
|
|
25
|
+
Requires-Dist: coreforged-mcp; extra == "keyring"
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: coreforged-mcp; extra == "all"
|
|
28
|
+
Provides-Extra: test
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == "test"
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "test"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# CoreforgedMCP
|
|
34
|
+
|
|
35
|
+
**One MCP server to dock them all.**
|
|
36
|
+
|
|
37
|
+
CoreforgedMCP is a gateway that consolidates multiple MCP servers behind a single endpoint. Instead of configuring 5 separate servers in your `.mcp.json`, you configure one — and control which plugins load with a single environment variable.
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Before: 5 servers × 5 processes × 5 config blocks
|
|
41
|
+
After: 1 server × 1 process × 1 config block
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install coreforged-mcp
|
|
48
|
+
coreforged-mcp init
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This adds CoreforgedMCP to your `.mcp.json`. Restart Claude Code — you're running.
|
|
52
|
+
|
|
53
|
+
## What You Get
|
|
54
|
+
|
|
55
|
+
### The Gateway (free, open source)
|
|
56
|
+
|
|
57
|
+
- **Plugin docking** — native Python plugins load in-process; proxy plugins spawn as subprocesses
|
|
58
|
+
- **Named loadouts** — switch your entire tool stack by setting `COREFORGED_LOADOUT=analytics`
|
|
59
|
+
- **Plugin discovery** — drop a plugin into `~/.coreforged/plugins/` and it auto-loads
|
|
60
|
+
- **Cross-platform** — Windows, Mac, Linux
|
|
61
|
+
|
|
62
|
+
### KeyRing (bundled)
|
|
63
|
+
|
|
64
|
+
Your API keys never enter the conversation. The keyring retrieves the secret, makes the authenticated API call, and returns only the response data. Every checkout is logged.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Agent: "Call the GitHub API with my token"
|
|
68
|
+
→ KeyRing retrieves token from encrypted store
|
|
69
|
+
→ KeyRing makes the API call
|
|
70
|
+
→ KeyRing returns the response data
|
|
71
|
+
→ Token never appears in tool results or context
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
### Basic (default plugins)
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"coreforged": {
|
|
82
|
+
"command": "coreforged-mcp",
|
|
83
|
+
"args": ["run"]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### With a loadout
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"mcpServers": {
|
|
94
|
+
"coreforged": {
|
|
95
|
+
"command": "coreforged-mcp",
|
|
96
|
+
"args": ["run"],
|
|
97
|
+
"env": {
|
|
98
|
+
"COREFORGED_LOADOUT": "analytics"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Specific plugins only
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"mcpServers": {
|
|
110
|
+
"coreforged": {
|
|
111
|
+
"command": "coreforged-mcp",
|
|
112
|
+
"args": ["run"],
|
|
113
|
+
"env": {
|
|
114
|
+
"COREFORGED_PLUGINS": "keyring,my-custom-plugin"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Installing Plugins
|
|
122
|
+
|
|
123
|
+
### From a zip file
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
coreforged-mcp install-plugin analytics-bundle.zip --key YOUR_LICENSE_KEY
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Plugins install to `~/.coreforged/plugins/` and are discovered automatically on next restart.
|
|
130
|
+
|
|
131
|
+
### From a directory
|
|
132
|
+
|
|
133
|
+
Drop any directory with a `plugin.json` manifest into `~/.coreforged/plugins/`:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
~/.coreforged/plugins/
|
|
137
|
+
├── my-plugin/
|
|
138
|
+
│ ├── plugin.json
|
|
139
|
+
│ └── server.py
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Writing a Plugin
|
|
143
|
+
|
|
144
|
+
A plugin is any Python module with a FastMCP instance. If it runs standalone, it docks into the gateway.
|
|
145
|
+
|
|
146
|
+
**1. Write the server**
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
# my-plugin/server.py
|
|
150
|
+
from mcp.server.fastmcp import FastMCP
|
|
151
|
+
|
|
152
|
+
mcp = FastMCP("my-plugin", instructions="What this does.")
|
|
153
|
+
|
|
154
|
+
@mcp.tool()
|
|
155
|
+
def my_tool(query: str) -> str:
|
|
156
|
+
"""Tool description."""
|
|
157
|
+
return do_something(query)
|
|
158
|
+
|
|
159
|
+
if __name__ == "__main__":
|
|
160
|
+
mcp.run()
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**2. Add the manifest**
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
// my-plugin/plugin.json
|
|
167
|
+
{
|
|
168
|
+
"name": "my-plugin",
|
|
169
|
+
"version": "0.1.0",
|
|
170
|
+
"description": "What it does",
|
|
171
|
+
"type": "native",
|
|
172
|
+
"module": "server",
|
|
173
|
+
"mcp_attr": "mcp",
|
|
174
|
+
"default": false
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**3. Test**
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Standalone
|
|
182
|
+
python my-plugin/server.py
|
|
183
|
+
|
|
184
|
+
# Docked
|
|
185
|
+
cp -r my-plugin ~/.coreforged/plugins/
|
|
186
|
+
coreforged-mcp status
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
A template plugin is included at `src/coreforged_mcp/plugins/_template/`.
|
|
190
|
+
|
|
191
|
+
## Plugin Types
|
|
192
|
+
|
|
193
|
+
| Type | How It Works | Best For |
|
|
194
|
+
|------|-------------|----------|
|
|
195
|
+
| **Native** | Python module imported in-process | Python tools, zero overhead |
|
|
196
|
+
| **Proxy** | External process spawned, tools bridged via JSON-RPC | Node.js, Go, Rust servers |
|
|
197
|
+
|
|
198
|
+
## CLI Commands
|
|
199
|
+
|
|
200
|
+
| Command | What It Does |
|
|
201
|
+
|---------|-------------|
|
|
202
|
+
| `coreforged-mcp run` | Start the gateway server |
|
|
203
|
+
| `coreforged-mcp status` | Show discovered plugins and loadouts |
|
|
204
|
+
| `coreforged-mcp init` | Add CoreforgedMCP to `.mcp.json` |
|
|
205
|
+
| `coreforged-mcp install-plugin <path> [--key KEY]` | Install a plugin from a zip |
|
|
206
|
+
|
|
207
|
+
## Available Plugins
|
|
208
|
+
|
|
209
|
+
| Plugin | Source | What It Does |
|
|
210
|
+
|--------|--------|-------------|
|
|
211
|
+
| **KeyRing** | Bundled | Sovereign secrets — API keys never enter context |
|
|
212
|
+
| Digital Analytics | [coreforged.com](https://coreforged.com) | GA4 + Search Console + PageSpeed |
|
|
213
|
+
| SEO Bundle | [coreforged.com](https://coreforged.com) | Keyword research + SERP analysis |
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
MIT — the gateway is free and open source. Some plugins on [coreforged.com](https://coreforged.com) are commercially licensed.
|
|
218
|
+
|
|
219
|
+
## Contributing
|
|
220
|
+
|
|
221
|
+
PRs welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
222
|
+
|
|
223
|
+
Built by [CoreForged LLC](https://coreforged.com).
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# CoreforgedMCP
|
|
2
|
+
|
|
3
|
+
**One MCP server to dock them all.**
|
|
4
|
+
|
|
5
|
+
CoreforgedMCP is a gateway that consolidates multiple MCP servers behind a single endpoint. Instead of configuring 5 separate servers in your `.mcp.json`, you configure one — and control which plugins load with a single environment variable.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Before: 5 servers × 5 processes × 5 config blocks
|
|
9
|
+
After: 1 server × 1 process × 1 config block
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install coreforged-mcp
|
|
16
|
+
coreforged-mcp init
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This adds CoreforgedMCP to your `.mcp.json`. Restart Claude Code — you're running.
|
|
20
|
+
|
|
21
|
+
## What You Get
|
|
22
|
+
|
|
23
|
+
### The Gateway (free, open source)
|
|
24
|
+
|
|
25
|
+
- **Plugin docking** — native Python plugins load in-process; proxy plugins spawn as subprocesses
|
|
26
|
+
- **Named loadouts** — switch your entire tool stack by setting `COREFORGED_LOADOUT=analytics`
|
|
27
|
+
- **Plugin discovery** — drop a plugin into `~/.coreforged/plugins/` and it auto-loads
|
|
28
|
+
- **Cross-platform** — Windows, Mac, Linux
|
|
29
|
+
|
|
30
|
+
### KeyRing (bundled)
|
|
31
|
+
|
|
32
|
+
Your API keys never enter the conversation. The keyring retrieves the secret, makes the authenticated API call, and returns only the response data. Every checkout is logged.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Agent: "Call the GitHub API with my token"
|
|
36
|
+
→ KeyRing retrieves token from encrypted store
|
|
37
|
+
→ KeyRing makes the API call
|
|
38
|
+
→ KeyRing returns the response data
|
|
39
|
+
→ Token never appears in tool results or context
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### Basic (default plugins)
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"coreforged": {
|
|
50
|
+
"command": "coreforged-mcp",
|
|
51
|
+
"args": ["run"]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### With a loadout
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"mcpServers": {
|
|
62
|
+
"coreforged": {
|
|
63
|
+
"command": "coreforged-mcp",
|
|
64
|
+
"args": ["run"],
|
|
65
|
+
"env": {
|
|
66
|
+
"COREFORGED_LOADOUT": "analytics"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Specific plugins only
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"coreforged": {
|
|
79
|
+
"command": "coreforged-mcp",
|
|
80
|
+
"args": ["run"],
|
|
81
|
+
"env": {
|
|
82
|
+
"COREFORGED_PLUGINS": "keyring,my-custom-plugin"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Installing Plugins
|
|
90
|
+
|
|
91
|
+
### From a zip file
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
coreforged-mcp install-plugin analytics-bundle.zip --key YOUR_LICENSE_KEY
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Plugins install to `~/.coreforged/plugins/` and are discovered automatically on next restart.
|
|
98
|
+
|
|
99
|
+
### From a directory
|
|
100
|
+
|
|
101
|
+
Drop any directory with a `plugin.json` manifest into `~/.coreforged/plugins/`:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
~/.coreforged/plugins/
|
|
105
|
+
├── my-plugin/
|
|
106
|
+
│ ├── plugin.json
|
|
107
|
+
│ └── server.py
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Writing a Plugin
|
|
111
|
+
|
|
112
|
+
A plugin is any Python module with a FastMCP instance. If it runs standalone, it docks into the gateway.
|
|
113
|
+
|
|
114
|
+
**1. Write the server**
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
# my-plugin/server.py
|
|
118
|
+
from mcp.server.fastmcp import FastMCP
|
|
119
|
+
|
|
120
|
+
mcp = FastMCP("my-plugin", instructions="What this does.")
|
|
121
|
+
|
|
122
|
+
@mcp.tool()
|
|
123
|
+
def my_tool(query: str) -> str:
|
|
124
|
+
"""Tool description."""
|
|
125
|
+
return do_something(query)
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
mcp.run()
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**2. Add the manifest**
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
// my-plugin/plugin.json
|
|
135
|
+
{
|
|
136
|
+
"name": "my-plugin",
|
|
137
|
+
"version": "0.1.0",
|
|
138
|
+
"description": "What it does",
|
|
139
|
+
"type": "native",
|
|
140
|
+
"module": "server",
|
|
141
|
+
"mcp_attr": "mcp",
|
|
142
|
+
"default": false
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**3. Test**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Standalone
|
|
150
|
+
python my-plugin/server.py
|
|
151
|
+
|
|
152
|
+
# Docked
|
|
153
|
+
cp -r my-plugin ~/.coreforged/plugins/
|
|
154
|
+
coreforged-mcp status
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
A template plugin is included at `src/coreforged_mcp/plugins/_template/`.
|
|
158
|
+
|
|
159
|
+
## Plugin Types
|
|
160
|
+
|
|
161
|
+
| Type | How It Works | Best For |
|
|
162
|
+
|------|-------------|----------|
|
|
163
|
+
| **Native** | Python module imported in-process | Python tools, zero overhead |
|
|
164
|
+
| **Proxy** | External process spawned, tools bridged via JSON-RPC | Node.js, Go, Rust servers |
|
|
165
|
+
|
|
166
|
+
## CLI Commands
|
|
167
|
+
|
|
168
|
+
| Command | What It Does |
|
|
169
|
+
|---------|-------------|
|
|
170
|
+
| `coreforged-mcp run` | Start the gateway server |
|
|
171
|
+
| `coreforged-mcp status` | Show discovered plugins and loadouts |
|
|
172
|
+
| `coreforged-mcp init` | Add CoreforgedMCP to `.mcp.json` |
|
|
173
|
+
| `coreforged-mcp install-plugin <path> [--key KEY]` | Install a plugin from a zip |
|
|
174
|
+
|
|
175
|
+
## Available Plugins
|
|
176
|
+
|
|
177
|
+
| Plugin | Source | What It Does |
|
|
178
|
+
|--------|--------|-------------|
|
|
179
|
+
| **KeyRing** | Bundled | Sovereign secrets — API keys never enter context |
|
|
180
|
+
| Digital Analytics | [coreforged.com](https://coreforged.com) | GA4 + Search Console + PageSpeed |
|
|
181
|
+
| SEO Bundle | [coreforged.com](https://coreforged.com) | Keyword research + SERP analysis |
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT — the gateway is free and open source. Some plugins on [coreforged.com](https://coreforged.com) are commercially licensed.
|
|
186
|
+
|
|
187
|
+
## Contributing
|
|
188
|
+
|
|
189
|
+
PRs welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
190
|
+
|
|
191
|
+
Built by [CoreForged LLC](https://coreforged.com).
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "coreforged-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MCP gateway that docks multiple servers behind one endpoint with named loadout profiles"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [{name = "CoreForged LLC", email = "corporate@coreforged.com"}]
|
|
13
|
+
keywords = ["mcp", "claude", "ai", "gateway", "plugins"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Topic :: Software Development :: Libraries",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
dependencies = [
|
|
27
|
+
"mcp[cli]>=1.0.0,<2",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
keyring = ["coreforged-mcp"]
|
|
32
|
+
all = ["coreforged-mcp"]
|
|
33
|
+
test = ["pytest>=8.0", "pytest-asyncio>=0.23"]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://coreforged.com/products/coreforged-mcp"
|
|
37
|
+
Repository = "https://github.com/coreforged/coreforged-mcp"
|
|
38
|
+
Documentation = "https://github.com/coreforged/coreforged-mcp#readme"
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
coreforged-mcp = "coreforged_mcp.cli:main"
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.packages.find]
|
|
44
|
+
where = ["src"]
|
|
45
|
+
include = ["coreforged_mcp*"]
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.package-data]
|
|
48
|
+
"coreforged_mcp" = ["plugins/*/plugin.json", "plugins/*/permissions.json", "plugins/*/secret_manifest.json", "loadouts.json"]
|
|
49
|
+
|
|
50
|
+
[tool.pytest.ini_options]
|
|
51
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""CoreforgedMCP CLI — manage the gateway and plugins."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def cmd_run(args):
|
|
10
|
+
"""Start the gateway server."""
|
|
11
|
+
from coreforged_mcp.gateway import gateway
|
|
12
|
+
gateway.run()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def cmd_status(args):
|
|
16
|
+
"""Show gateway status without starting the server."""
|
|
17
|
+
from coreforged_mcp.gateway import _discover_plugins, _plugin_status, _loadouts, _load_loadouts
|
|
18
|
+
_load_loadouts()
|
|
19
|
+
registry = _discover_plugins()
|
|
20
|
+
print(f"CoreforgedMCP v{_get_version()}")
|
|
21
|
+
print(f"Discovered plugins: {len(registry)}")
|
|
22
|
+
for name, manifest in registry.items():
|
|
23
|
+
source = manifest.get("_source", "?")
|
|
24
|
+
default = "default" if manifest.get("default") else "opt-in"
|
|
25
|
+
print(f" {name} ({source}, {default}): {manifest.get('description', '')}")
|
|
26
|
+
if _loadouts:
|
|
27
|
+
print(f"\nLoadouts: {len(_loadouts)}")
|
|
28
|
+
for name, profile in _loadouts.items():
|
|
29
|
+
print(f" {name}: {profile.get('description', '')}")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def cmd_init(args):
|
|
33
|
+
"""Initialize CoreforgedMCP config for this project."""
|
|
34
|
+
mcp_json_path = os.path.join(os.getcwd(), ".mcp.json")
|
|
35
|
+
|
|
36
|
+
if os.path.exists(mcp_json_path):
|
|
37
|
+
with open(mcp_json_path, encoding="utf-8") as f:
|
|
38
|
+
config = json.load(f)
|
|
39
|
+
else:
|
|
40
|
+
config = {}
|
|
41
|
+
|
|
42
|
+
servers = config.setdefault("mcpServers", {})
|
|
43
|
+
if "coreforged" in servers:
|
|
44
|
+
print("CoreforgedMCP already configured in .mcp.json")
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
servers["coreforged"] = {
|
|
48
|
+
"command": "coreforged-mcp",
|
|
49
|
+
"args": ["run"],
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
with open(mcp_json_path, "w", encoding="utf-8") as f:
|
|
53
|
+
json.dump(config, f, indent=2)
|
|
54
|
+
|
|
55
|
+
print(f"Added CoreforgedMCP to {mcp_json_path}")
|
|
56
|
+
print("Restart Claude Code to load the gateway.")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def cmd_install_plugin(args):
|
|
60
|
+
"""Install a plugin from a zip file."""
|
|
61
|
+
import zipfile
|
|
62
|
+
import shutil
|
|
63
|
+
|
|
64
|
+
zip_path = args.path
|
|
65
|
+
if not os.path.isfile(zip_path):
|
|
66
|
+
print(f"Error: {zip_path} not found", file=sys.stderr)
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
|
|
69
|
+
user_dir = os.path.join(os.path.expanduser("~"), ".coreforged", "plugins")
|
|
70
|
+
os.makedirs(user_dir, exist_ok=True)
|
|
71
|
+
|
|
72
|
+
with zipfile.ZipFile(zip_path, "r") as zf:
|
|
73
|
+
names = zf.namelist()
|
|
74
|
+
manifest_candidates = [n for n in names if n.endswith("plugin.json")]
|
|
75
|
+
if not manifest_candidates:
|
|
76
|
+
print("Error: no plugin.json found in archive", file=sys.stderr)
|
|
77
|
+
sys.exit(1)
|
|
78
|
+
|
|
79
|
+
manifest_path = manifest_candidates[0]
|
|
80
|
+
manifest_data = json.loads(zf.read(manifest_path))
|
|
81
|
+
plugin_name = manifest_data.get("name", os.path.basename(zip_path).replace(".zip", ""))
|
|
82
|
+
|
|
83
|
+
if args.key:
|
|
84
|
+
manifest_data["license_key"] = args.key
|
|
85
|
+
|
|
86
|
+
dest = os.path.join(user_dir, plugin_name)
|
|
87
|
+
if os.path.exists(dest):
|
|
88
|
+
shutil.rmtree(dest)
|
|
89
|
+
|
|
90
|
+
prefix = os.path.dirname(manifest_path)
|
|
91
|
+
for member in names:
|
|
92
|
+
if prefix and not member.startswith(prefix):
|
|
93
|
+
continue
|
|
94
|
+
rel = member[len(prefix):].lstrip("/") if prefix else member
|
|
95
|
+
if not rel or rel.endswith("/"):
|
|
96
|
+
continue
|
|
97
|
+
target = os.path.join(dest, rel)
|
|
98
|
+
os.makedirs(os.path.dirname(target), exist_ok=True)
|
|
99
|
+
with open(target, "wb") as out:
|
|
100
|
+
out.write(zf.read(member))
|
|
101
|
+
|
|
102
|
+
if args.key:
|
|
103
|
+
manifest_out = os.path.join(dest, "plugin.json")
|
|
104
|
+
with open(manifest_out, "w", encoding="utf-8") as f:
|
|
105
|
+
json.dump(manifest_data, f, indent=2)
|
|
106
|
+
|
|
107
|
+
print(f"Installed plugin '{plugin_name}' to {dest}")
|
|
108
|
+
print("Restart Claude Code to load the new plugin.")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _get_version():
|
|
112
|
+
from coreforged_mcp import __version__
|
|
113
|
+
return __version__
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def main():
|
|
117
|
+
parser = argparse.ArgumentParser(
|
|
118
|
+
prog="coreforged-mcp",
|
|
119
|
+
description="CoreforgedMCP — one MCP server to dock them all",
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument("--version", action="version", version=f"%(prog)s {_get_version()}")
|
|
122
|
+
sub = parser.add_subparsers(dest="command")
|
|
123
|
+
|
|
124
|
+
sub.add_parser("run", help="Start the gateway server")
|
|
125
|
+
sub.add_parser("status", help="Show discovered plugins and loadouts")
|
|
126
|
+
sub.add_parser("init", help="Add CoreforgedMCP to .mcp.json in the current directory")
|
|
127
|
+
|
|
128
|
+
install = sub.add_parser("install-plugin", help="Install a plugin from a zip file")
|
|
129
|
+
install.add_argument("path", help="Path to plugin .zip file")
|
|
130
|
+
install.add_argument("--key", help="License key for paid plugins")
|
|
131
|
+
|
|
132
|
+
args = parser.parse_args()
|
|
133
|
+
|
|
134
|
+
commands = {
|
|
135
|
+
"run": cmd_run,
|
|
136
|
+
"status": cmd_status,
|
|
137
|
+
"init": cmd_init,
|
|
138
|
+
"install-plugin": cmd_install_plugin,
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if args.command in commands:
|
|
142
|
+
commands[args.command](args)
|
|
143
|
+
else:
|
|
144
|
+
parser.print_help()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
main()
|