axiomatic-mcp 0.0a3__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.
- axiomatic_mcp-0.0a3/PKG-INFO +232 -0
- axiomatic_mcp-0.0a3/README.md +203 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/__init__.py +3 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/__init__.py +9 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/code_execution/__init__.py +5 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/code_execution/__main__.py +4 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/code_execution/server.py +47 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/documents/__init__.py +5 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/documents/__main__.py +4 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/documents/server.py +41 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/equations/__init__.py +5 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/equations/__main__.py +4 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/equations/server.py +51 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/pic/__init__.py +5 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/pic/__main__.py +4 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/pic/server.py +48 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/plots/__init__.py +6 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/plots/__main__.py +4 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/servers/plots/server.py +127 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/shared/__init__.py +7 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/shared/api_client.py +50 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp/shared/documents/pdf_to_markdown.py +37 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp.egg-info/PKG-INFO +232 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp.egg-info/SOURCES.txt +28 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp.egg-info/dependency_links.txt +1 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp.egg-info/entry_points.txt +6 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp.egg-info/requires.txt +10 -0
- axiomatic_mcp-0.0a3/axiomatic_mcp.egg-info/top_level.txt +1 -0
- axiomatic_mcp-0.0a3/pyproject.toml +64 -0
- axiomatic_mcp-0.0a3/setup.cfg +4 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: axiomatic-mcp
|
|
3
|
+
Version: 0.0a3
|
|
4
|
+
Summary: Modular MCP servers for Axiomatic_AI
|
|
5
|
+
Author-email: Axiomatic Team <developers@axiomatic.ai>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/axiomatic/ax-mcp
|
|
8
|
+
Project-URL: Issues, https://github.com/axiomatic/ax-mcp/issues
|
|
9
|
+
Keywords: mcp,axiomatic,ai,fastmcp
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: fastmcp>=0.1.0
|
|
21
|
+
Requires-Dist: pydantic>=2.0.0
|
|
22
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
23
|
+
Requires-Dist: httpx>=0.25.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
26
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
29
|
+
|
|
30
|
+
# Axiomatic MCP Servers
|
|
31
|
+
|
|
32
|
+
MCP (Model Context Protocol) servers that provide AI assistants with access to the Axiomatic_AI Platform - a suite of advanced tools for scientific computing, document processing, and photonic circuit design.
|
|
33
|
+
|
|
34
|
+
## Available Servers
|
|
35
|
+
|
|
36
|
+
### 📄 [Documents Server](./axiomatic_mcp/servers/documents/)
|
|
37
|
+
|
|
38
|
+
Convert PDF documents to markdown with advanced OCR and layout understanding.
|
|
39
|
+
|
|
40
|
+
### 🖌️ [Equations Server](./axiomatic_mcp/servers/equations/)
|
|
41
|
+
|
|
42
|
+
Compose equation of your interest based on information in the scientific paper.
|
|
43
|
+
|
|
44
|
+
### 🔬 [PIC Designer Server](./axiomatic_mcp/servers/pic/)
|
|
45
|
+
|
|
46
|
+
Design photonic integrated circuits using natural language descriptions.
|
|
47
|
+
|
|
48
|
+
### 📊 [Plots Server](./axiomatic_mcp/servers/plots/)
|
|
49
|
+
|
|
50
|
+
Extract numerical data from plot images for analysis and reproduction.
|
|
51
|
+
|
|
52
|
+
### 🖥️ [Code Execution Server](./axiomatic_mcp/servers/code_execution/)
|
|
53
|
+
|
|
54
|
+
Execute Python code in a secure environment with support for selected libraries (`gdsfactory`, `z3`, `json`).
|
|
55
|
+
Useful for photonic design workflows, symbolic reasoning, and structured data manipulation.
|
|
56
|
+
|
|
57
|
+
## Getting an API Key
|
|
58
|
+
|
|
59
|
+
All Axiomatic MCP servers require an API key:
|
|
60
|
+
|
|
61
|
+
1. Contact developers@axiomatic-ai.com to request access
|
|
62
|
+
2. Add the API key to your MCP client configuration as `AXIOMATIC_API_KEY`
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
Installation instructions can be found for each specific server in their README.
|
|
67
|
+
|
|
68
|
+
### Setting up MCP Servers in AI Clients
|
|
69
|
+
|
|
70
|
+
#### Claude Desktop
|
|
71
|
+
|
|
72
|
+
1. Open Claude Desktop settings
|
|
73
|
+
2. Navigate to Developer → Edit MCP config
|
|
74
|
+
3. Add the server configuration(s) above
|
|
75
|
+
4. Restart Claude Desktop
|
|
76
|
+
|
|
77
|
+
#### Cursor
|
|
78
|
+
|
|
79
|
+
1. Open Cursor settings (Cmd/Ctrl + ,)
|
|
80
|
+
2. Search for "MCP"
|
|
81
|
+
3. Add the server configuration(s) to the MCP settings
|
|
82
|
+
4. Restart Cursor
|
|
83
|
+
|
|
84
|
+
#### Other MCP Clients
|
|
85
|
+
|
|
86
|
+
Refer to your client's documentation for MCP server configuration.
|
|
87
|
+
|
|
88
|
+
## Development
|
|
89
|
+
|
|
90
|
+
### Local Development Setup
|
|
91
|
+
|
|
92
|
+
1. Clone the repository:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
git clone https://github.com/axiomatic/ax-mcp.git
|
|
96
|
+
cd ax-mcp
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
2. Install in development mode:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
make install-dev
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
3. Configure your MCP client to use local Python modules:
|
|
106
|
+
|
|
107
|
+
> See specific MCP server README for specific installation instructions.
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"axiomatic-documents": {
|
|
112
|
+
"command": "python",
|
|
113
|
+
"args": ["-m", "axiomatic_mcp.servers.documents"],
|
|
114
|
+
"env": {
|
|
115
|
+
"AXIOMATIC_API_KEY": "your-api-key-here"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Adding a New Server
|
|
122
|
+
|
|
123
|
+
1. Create server directory:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
mkdir axiomatic_mcp/servers/my_domain
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
2. Create `__init__.py`:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from .server import MyDomainServer
|
|
133
|
+
|
|
134
|
+
def main():
|
|
135
|
+
server = MyDomainServer()
|
|
136
|
+
server.run()
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
2. Create `__main__.py`:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from . import main
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
main()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
3. Implement server in `server.py`:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from fastmcp import FastMCP
|
|
152
|
+
|
|
153
|
+
mcp = FastMCP(
|
|
154
|
+
name="NAME",
|
|
155
|
+
instructions="""GIVE NICE INSTRUCTIONS""",
|
|
156
|
+
version="0.0.1",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
@mcp.tool(
|
|
160
|
+
name="tool_name",
|
|
161
|
+
description="DESCRIPTION",
|
|
162
|
+
tags=["TAG"],
|
|
163
|
+
)
|
|
164
|
+
def my_tool():
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
# Add more tools as needed
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
4. Add entry point to `pyproject.toml`:
|
|
171
|
+
|
|
172
|
+
```toml
|
|
173
|
+
[project.scripts]
|
|
174
|
+
axiomatic-mydomain = "axiomatic_mcp.servers.my_domain:main"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
5. Update README.md with instructions on installing your server. You can generate the "Add to cursor" button [here](https://docs.cursor.com/en/tools/developers)
|
|
178
|
+
|
|
179
|
+
6. Don't forget to link to your server's README.md in the main project README.md
|
|
180
|
+
|
|
181
|
+
### Release Process
|
|
182
|
+
|
|
183
|
+
#### Publishing a Release
|
|
184
|
+
|
|
185
|
+
1. Create a new release branch
|
|
186
|
+
1. Update version in `pyproject.toml`
|
|
187
|
+
1. Commit and push changes
|
|
188
|
+
1. Create a pull request titled "Release: YOUR FEATURE(s)". Include detailed description of what's included in the release.
|
|
189
|
+
1. Create a GitHub release with tag `vX.Y.Z`
|
|
190
|
+
1. GitHub Actions automatically publishes to PyPI
|
|
191
|
+
|
|
192
|
+
The package is available at: https://pypi.org/project/axiomatic-mcp/
|
|
193
|
+
|
|
194
|
+
## Contributing
|
|
195
|
+
|
|
196
|
+
We welcome contributions! To add a new server or improve existing ones:
|
|
197
|
+
|
|
198
|
+
1. Fork the repository
|
|
199
|
+
2. Create a feature branch
|
|
200
|
+
3. Implement your changes following the existing patterns
|
|
201
|
+
4. Add documentation to your server directory
|
|
202
|
+
5. Submit a pull request
|
|
203
|
+
|
|
204
|
+
For detailed guidelines on adding new servers, see the [Development](#development) section.
|
|
205
|
+
|
|
206
|
+
## Troubleshooting
|
|
207
|
+
|
|
208
|
+
### Server not appearing in Cursor
|
|
209
|
+
|
|
210
|
+
1. Restart Cursor after updating MCP settings
|
|
211
|
+
2. Check the Output panel (View → Output → MCP) for errors
|
|
212
|
+
3. Verify the command path is correct
|
|
213
|
+
|
|
214
|
+
### Multiple servers overwhelming the LLM
|
|
215
|
+
|
|
216
|
+
Install only the domain servers you need. Each server runs independently, so you can add/remove them as needed.
|
|
217
|
+
|
|
218
|
+
### API connection errors
|
|
219
|
+
|
|
220
|
+
1. Verify your API key is set correctly
|
|
221
|
+
2. Check internet connection
|
|
222
|
+
|
|
223
|
+
## Support
|
|
224
|
+
|
|
225
|
+
- **Issues**: [GitHub Issues](https://github.com/axiomatic/ax-mcp/issues)
|
|
226
|
+
- **Email**: developers@axiomatic-ai.com
|
|
227
|
+
|
|
228
|
+
## Creating >>Add to Cursor<< button:
|
|
229
|
+
|
|
230
|
+
Copy your MCP client configuration and paste it there:
|
|
231
|
+
|
|
232
|
+
https://docs.cursor.com/en/tools/developers#generate-install-link
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Axiomatic MCP Servers
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) servers that provide AI assistants with access to the Axiomatic_AI Platform - a suite of advanced tools for scientific computing, document processing, and photonic circuit design.
|
|
4
|
+
|
|
5
|
+
## Available Servers
|
|
6
|
+
|
|
7
|
+
### 📄 [Documents Server](./axiomatic_mcp/servers/documents/)
|
|
8
|
+
|
|
9
|
+
Convert PDF documents to markdown with advanced OCR and layout understanding.
|
|
10
|
+
|
|
11
|
+
### 🖌️ [Equations Server](./axiomatic_mcp/servers/equations/)
|
|
12
|
+
|
|
13
|
+
Compose equation of your interest based on information in the scientific paper.
|
|
14
|
+
|
|
15
|
+
### 🔬 [PIC Designer Server](./axiomatic_mcp/servers/pic/)
|
|
16
|
+
|
|
17
|
+
Design photonic integrated circuits using natural language descriptions.
|
|
18
|
+
|
|
19
|
+
### 📊 [Plots Server](./axiomatic_mcp/servers/plots/)
|
|
20
|
+
|
|
21
|
+
Extract numerical data from plot images for analysis and reproduction.
|
|
22
|
+
|
|
23
|
+
### 🖥️ [Code Execution Server](./axiomatic_mcp/servers/code_execution/)
|
|
24
|
+
|
|
25
|
+
Execute Python code in a secure environment with support for selected libraries (`gdsfactory`, `z3`, `json`).
|
|
26
|
+
Useful for photonic design workflows, symbolic reasoning, and structured data manipulation.
|
|
27
|
+
|
|
28
|
+
## Getting an API Key
|
|
29
|
+
|
|
30
|
+
All Axiomatic MCP servers require an API key:
|
|
31
|
+
|
|
32
|
+
1. Contact developers@axiomatic-ai.com to request access
|
|
33
|
+
2. Add the API key to your MCP client configuration as `AXIOMATIC_API_KEY`
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
Installation instructions can be found for each specific server in their README.
|
|
38
|
+
|
|
39
|
+
### Setting up MCP Servers in AI Clients
|
|
40
|
+
|
|
41
|
+
#### Claude Desktop
|
|
42
|
+
|
|
43
|
+
1. Open Claude Desktop settings
|
|
44
|
+
2. Navigate to Developer → Edit MCP config
|
|
45
|
+
3. Add the server configuration(s) above
|
|
46
|
+
4. Restart Claude Desktop
|
|
47
|
+
|
|
48
|
+
#### Cursor
|
|
49
|
+
|
|
50
|
+
1. Open Cursor settings (Cmd/Ctrl + ,)
|
|
51
|
+
2. Search for "MCP"
|
|
52
|
+
3. Add the server configuration(s) to the MCP settings
|
|
53
|
+
4. Restart Cursor
|
|
54
|
+
|
|
55
|
+
#### Other MCP Clients
|
|
56
|
+
|
|
57
|
+
Refer to your client's documentation for MCP server configuration.
|
|
58
|
+
|
|
59
|
+
## Development
|
|
60
|
+
|
|
61
|
+
### Local Development Setup
|
|
62
|
+
|
|
63
|
+
1. Clone the repository:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/axiomatic/ax-mcp.git
|
|
67
|
+
cd ax-mcp
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
2. Install in development mode:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
make install-dev
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
3. Configure your MCP client to use local Python modules:
|
|
77
|
+
|
|
78
|
+
> See specific MCP server README for specific installation instructions.
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"axiomatic-documents": {
|
|
83
|
+
"command": "python",
|
|
84
|
+
"args": ["-m", "axiomatic_mcp.servers.documents"],
|
|
85
|
+
"env": {
|
|
86
|
+
"AXIOMATIC_API_KEY": "your-api-key-here"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Adding a New Server
|
|
93
|
+
|
|
94
|
+
1. Create server directory:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
mkdir axiomatic_mcp/servers/my_domain
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
2. Create `__init__.py`:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from .server import MyDomainServer
|
|
104
|
+
|
|
105
|
+
def main():
|
|
106
|
+
server = MyDomainServer()
|
|
107
|
+
server.run()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
2. Create `__main__.py`:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from . import main
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
main()
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
3. Implement server in `server.py`:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from fastmcp import FastMCP
|
|
123
|
+
|
|
124
|
+
mcp = FastMCP(
|
|
125
|
+
name="NAME",
|
|
126
|
+
instructions="""GIVE NICE INSTRUCTIONS""",
|
|
127
|
+
version="0.0.1",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
@mcp.tool(
|
|
131
|
+
name="tool_name",
|
|
132
|
+
description="DESCRIPTION",
|
|
133
|
+
tags=["TAG"],
|
|
134
|
+
)
|
|
135
|
+
def my_tool():
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
# Add more tools as needed
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
4. Add entry point to `pyproject.toml`:
|
|
142
|
+
|
|
143
|
+
```toml
|
|
144
|
+
[project.scripts]
|
|
145
|
+
axiomatic-mydomain = "axiomatic_mcp.servers.my_domain:main"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
5. Update README.md with instructions on installing your server. You can generate the "Add to cursor" button [here](https://docs.cursor.com/en/tools/developers)
|
|
149
|
+
|
|
150
|
+
6. Don't forget to link to your server's README.md in the main project README.md
|
|
151
|
+
|
|
152
|
+
### Release Process
|
|
153
|
+
|
|
154
|
+
#### Publishing a Release
|
|
155
|
+
|
|
156
|
+
1. Create a new release branch
|
|
157
|
+
1. Update version in `pyproject.toml`
|
|
158
|
+
1. Commit and push changes
|
|
159
|
+
1. Create a pull request titled "Release: YOUR FEATURE(s)". Include detailed description of what's included in the release.
|
|
160
|
+
1. Create a GitHub release with tag `vX.Y.Z`
|
|
161
|
+
1. GitHub Actions automatically publishes to PyPI
|
|
162
|
+
|
|
163
|
+
The package is available at: https://pypi.org/project/axiomatic-mcp/
|
|
164
|
+
|
|
165
|
+
## Contributing
|
|
166
|
+
|
|
167
|
+
We welcome contributions! To add a new server or improve existing ones:
|
|
168
|
+
|
|
169
|
+
1. Fork the repository
|
|
170
|
+
2. Create a feature branch
|
|
171
|
+
3. Implement your changes following the existing patterns
|
|
172
|
+
4. Add documentation to your server directory
|
|
173
|
+
5. Submit a pull request
|
|
174
|
+
|
|
175
|
+
For detailed guidelines on adding new servers, see the [Development](#development) section.
|
|
176
|
+
|
|
177
|
+
## Troubleshooting
|
|
178
|
+
|
|
179
|
+
### Server not appearing in Cursor
|
|
180
|
+
|
|
181
|
+
1. Restart Cursor after updating MCP settings
|
|
182
|
+
2. Check the Output panel (View → Output → MCP) for errors
|
|
183
|
+
3. Verify the command path is correct
|
|
184
|
+
|
|
185
|
+
### Multiple servers overwhelming the LLM
|
|
186
|
+
|
|
187
|
+
Install only the domain servers you need. Each server runs independently, so you can add/remove them as needed.
|
|
188
|
+
|
|
189
|
+
### API connection errors
|
|
190
|
+
|
|
191
|
+
1. Verify your API key is set correctly
|
|
192
|
+
2. Check internet connection
|
|
193
|
+
|
|
194
|
+
## Support
|
|
195
|
+
|
|
196
|
+
- **Issues**: [GitHub Issues](https://github.com/axiomatic/ax-mcp/issues)
|
|
197
|
+
- **Email**: developers@axiomatic-ai.com
|
|
198
|
+
|
|
199
|
+
## Creating >>Add to Cursor<< button:
|
|
200
|
+
|
|
201
|
+
Copy your MCP client configuration and paste it there:
|
|
202
|
+
|
|
203
|
+
https://docs.cursor.com/en/tools/developers#generate-install-link
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Code Execution MCP server."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
from fastmcp import FastMCP
|
|
6
|
+
from fastmcp.tools.tool import ToolResult
|
|
7
|
+
from mcp.types import TextContent
|
|
8
|
+
|
|
9
|
+
from ...shared import AxiomaticAPIClient
|
|
10
|
+
|
|
11
|
+
mcp = FastMCP(
|
|
12
|
+
name="Axiomatic Code Execution",
|
|
13
|
+
instructions="""This server provides tools to execute Python code
|
|
14
|
+
securely in a sandboxed environment with limited supported libraries.""",
|
|
15
|
+
version="0.0.1",
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@mcp.tool(
|
|
20
|
+
name="code_execution",
|
|
21
|
+
description="Execute Python code in a secure environment and return stdout or error trace",
|
|
22
|
+
tags=["python", "execute", "sandbox"],
|
|
23
|
+
)
|
|
24
|
+
async def execute_code(
|
|
25
|
+
code: Annotated[str, "The Python code to execute"],
|
|
26
|
+
) -> ToolResult:
|
|
27
|
+
"""Execute Python code securely in the Axiomatic environment."""
|
|
28
|
+
|
|
29
|
+
data = {"code": code}
|
|
30
|
+
response = AxiomaticAPIClient().post("/code-execution/python/execute", data=data)
|
|
31
|
+
|
|
32
|
+
output: str = response.get("output", "")
|
|
33
|
+
is_success: bool = response.get("is_success", False)
|
|
34
|
+
error_trace: str | None = response.get("error_trace")
|
|
35
|
+
|
|
36
|
+
text_output = f"Execution Result:\n\n{output}" if is_success else f"Execution Failed:\n\n{error_trace}"
|
|
37
|
+
|
|
38
|
+
return ToolResult(
|
|
39
|
+
content=[TextContent(type="text", text=text_output)],
|
|
40
|
+
structured_content={
|
|
41
|
+
"execution_result": {
|
|
42
|
+
"output": output,
|
|
43
|
+
"is_success": is_success,
|
|
44
|
+
"error_trace": error_trace,
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Documents MCP server for filesystem document operations."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
from fastmcp import FastMCP
|
|
7
|
+
from fastmcp.exceptions import ToolError
|
|
8
|
+
from fastmcp.tools.tool import ToolResult
|
|
9
|
+
from mcp.types import TextContent
|
|
10
|
+
|
|
11
|
+
from ...shared.documents.pdf_to_markdown import pdf_to_markdown
|
|
12
|
+
|
|
13
|
+
mcp = FastMCP(
|
|
14
|
+
name="Axiomatic Documents Server",
|
|
15
|
+
instructions="""This server provides tools to read, analyze, and process documents
|
|
16
|
+
from the filesystem using the Axiomatic_AI Platform.""",
|
|
17
|
+
version="0.0.1",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@mcp.tool(
|
|
22
|
+
name="document_to_markdown",
|
|
23
|
+
description="Convert a PDF document to markdown using Axiomatic's advanced OCR.",
|
|
24
|
+
tags=["document", "filesystem", "analyze"],
|
|
25
|
+
)
|
|
26
|
+
async def document_to_markdown(
|
|
27
|
+
file_path: Annotated[Path, "The absolute path to the PDF file to analyze"],
|
|
28
|
+
) -> ToolResult:
|
|
29
|
+
try:
|
|
30
|
+
response = await pdf_to_markdown(file_path)
|
|
31
|
+
name = file_path.stem + ".md"
|
|
32
|
+
return ToolResult(
|
|
33
|
+
content=[TextContent(type="text", text=f"Generated markdown for: {name}\n\n```markdown\n{response.markdown}\n```")],
|
|
34
|
+
structured_content={
|
|
35
|
+
"suggestions": [
|
|
36
|
+
{"type": "create_file", "path": name, "content": response.markdown, "description": f"Create {name} with the generated markdown"}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
)
|
|
40
|
+
except Exception as e:
|
|
41
|
+
raise ToolError(f"Failed to analyze PDF document: {e!s}") from e
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Annotated
|
|
3
|
+
|
|
4
|
+
from fastmcp import FastMCP
|
|
5
|
+
from fastmcp.exceptions import ToolError
|
|
6
|
+
from fastmcp.tools.tool import ToolResult
|
|
7
|
+
from mcp.types import TextContent
|
|
8
|
+
|
|
9
|
+
from axiomatic_mcp.shared.documents.pdf_to_markdown import pdf_to_markdown
|
|
10
|
+
|
|
11
|
+
from ...shared import AxiomaticAPIClient
|
|
12
|
+
|
|
13
|
+
mcp = FastMCP(
|
|
14
|
+
name="Axiomatic Equations Server",
|
|
15
|
+
instructions="""This server provides tools to compose and analyze equations.""",
|
|
16
|
+
version="0.0.1",
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@mcp.tool(
|
|
21
|
+
name="compose_expression",
|
|
22
|
+
description=(
|
|
23
|
+
"Compose an expression of your interest given the information form the source documents "
|
|
24
|
+
"and equations residing there. Provide descrption of the expression you want to compose."
|
|
25
|
+
),
|
|
26
|
+
tags=["equations", "compose"],
|
|
27
|
+
)
|
|
28
|
+
async def compose_expression(
|
|
29
|
+
file_path: Annotated[Path, "The absolute path to the PDF file to analyze"], task: Annotated[str, "The task to be done for expression composition"]
|
|
30
|
+
) -> ToolResult:
|
|
31
|
+
"""If you have scientific text with equations, but you dont see the equation you're
|
|
32
|
+
interested in then use this tool and simply say: >>Express the energy in terms of
|
|
33
|
+
valocity and position<<, or something like that. The tool will return the desired expression
|
|
34
|
+
together with sympy code that explain how it was derived."""
|
|
35
|
+
try:
|
|
36
|
+
response = await pdf_to_markdown(file_path)
|
|
37
|
+
|
|
38
|
+
input_body = {"source_doc": response.markdown, "task": task}
|
|
39
|
+
|
|
40
|
+
response = AxiomaticAPIClient().post("/document/expression/compose", data=input_body)
|
|
41
|
+
|
|
42
|
+
return ToolResult(
|
|
43
|
+
content=[
|
|
44
|
+
TextContent(type="text", text=f"Composed expression: {response.get('composed_expression')}"),
|
|
45
|
+
TextContent(type="text", text=f"Comments: {response.get('comments')}"),
|
|
46
|
+
TextContent(type="text", text=f"Composition code: {response.get('composition_code')}"),
|
|
47
|
+
]
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
except Exception as e:
|
|
51
|
+
raise ToolError(f"Failed to analyze PDF document: {e!s}") from e
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""PIC (Photonic Integrated Circuit) domain MCP server."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
from fastmcp import FastMCP
|
|
6
|
+
from fastmcp.tools.tool import ToolResult
|
|
7
|
+
from mcp.types import TextContent
|
|
8
|
+
|
|
9
|
+
from ...shared import AxiomaticAPIClient
|
|
10
|
+
|
|
11
|
+
mcp = FastMCP(
|
|
12
|
+
name="Axiomatic PIC Designer",
|
|
13
|
+
instructions="""This server provides tools to design, optimize,
|
|
14
|
+
and simulate photonic integrated circuits.""",
|
|
15
|
+
version="0.0.1",
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@mcp.tool(
|
|
20
|
+
name="design_circuit",
|
|
21
|
+
description="Design a photonic integrated circuit and optionally create a Python file",
|
|
22
|
+
tags=["design", "gfsfactory"],
|
|
23
|
+
)
|
|
24
|
+
async def design(
|
|
25
|
+
query: Annotated[str, "The query to design the circuit"],
|
|
26
|
+
existing_code: Annotated[str | None, "Existing code to use as a reference to refine"] = None,
|
|
27
|
+
) -> ToolResult:
|
|
28
|
+
"""Design a photonic integrated circuit."""
|
|
29
|
+
data = {
|
|
30
|
+
"query": query,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if existing_code:
|
|
34
|
+
data["code"] = existing_code
|
|
35
|
+
|
|
36
|
+
response = AxiomaticAPIClient().post("/pic/circuit/refine", data=data)
|
|
37
|
+
code: str = response["code"]
|
|
38
|
+
|
|
39
|
+
file_name = "circuit.py"
|
|
40
|
+
|
|
41
|
+
return ToolResult(
|
|
42
|
+
content=[TextContent(type="text", text=f"Generated photonic circuit design for: {file_name}\n\n```python\n{code}\n```")],
|
|
43
|
+
structured_content={
|
|
44
|
+
"suggestions": [
|
|
45
|
+
{"type": "create_file", "path": file_name, "content": code, "description": f"Create {file_name} with the generated circuit design"}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Plot Parser MCP server"""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import mimetypes
|
|
5
|
+
import random
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Annotated
|
|
8
|
+
|
|
9
|
+
from fastmcp import FastMCP
|
|
10
|
+
from fastmcp.exceptions import ToolError
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
|
|
13
|
+
from ...shared import AxiomaticAPIClient
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Point(BaseModel):
|
|
17
|
+
"""Extracted point of a series from a plot"""
|
|
18
|
+
|
|
19
|
+
x_value: float
|
|
20
|
+
y_value: float
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SeriesPoints(BaseModel):
|
|
24
|
+
"""Extracted series from a plot"""
|
|
25
|
+
|
|
26
|
+
series_unique_id: int
|
|
27
|
+
points: list[Point]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class SeriesPointsData(BaseModel):
|
|
31
|
+
"""A list of points from each series in a plot"""
|
|
32
|
+
|
|
33
|
+
series_points: list[SeriesPoints]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def process_plot_parser_output(response_json, max_points: int = 100, sig_figs: int = 5) -> SeriesPointsData:
|
|
37
|
+
extracted_series_list: list[SeriesPoints] = []
|
|
38
|
+
|
|
39
|
+
series_array = (response_json or {}).get("extracted_series") or []
|
|
40
|
+
for idx, extracted_series in enumerate(series_array):
|
|
41
|
+
all_extracted_points = extracted_series.get("points") or []
|
|
42
|
+
if not all_extracted_points:
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
sample_size = min(max_points, len(all_extracted_points))
|
|
46
|
+
selected_points = random.sample(all_extracted_points, sample_size)
|
|
47
|
+
|
|
48
|
+
condensed_points_list: list[Point] = []
|
|
49
|
+
for point in selected_points:
|
|
50
|
+
x_raw = point.get("value_x")
|
|
51
|
+
y_raw = point.get("value_y")
|
|
52
|
+
if x_raw is None or y_raw is None:
|
|
53
|
+
continue
|
|
54
|
+
try:
|
|
55
|
+
x_num = float(x_raw)
|
|
56
|
+
y_num = float(y_raw)
|
|
57
|
+
except (TypeError, ValueError):
|
|
58
|
+
continue
|
|
59
|
+
if not math.isfinite(x_num) or not math.isfinite(y_num):
|
|
60
|
+
continue
|
|
61
|
+
x_val = float(format(x_num, f".{sig_figs}g"))
|
|
62
|
+
y_val = float(format(y_num, f".{sig_figs}g"))
|
|
63
|
+
condensed_points_list.append(Point(x_value=x_val, y_value=y_val))
|
|
64
|
+
if not condensed_points_list:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
series_id = extracted_series.get("id", idx)
|
|
68
|
+
try:
|
|
69
|
+
series_id = int(series_id)
|
|
70
|
+
except (TypeError, ValueError):
|
|
71
|
+
series_id = idx
|
|
72
|
+
|
|
73
|
+
series = SeriesPoints(series_unique_id=series_id, points=condensed_points_list)
|
|
74
|
+
extracted_series_list.append(series)
|
|
75
|
+
return SeriesPointsData(series_points=extracted_series_list)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
PLOTS_SERVER_INSTRUCTIONS = """This server hosts tools for extracting numerical data from plot images.
|
|
79
|
+
It can analyze line plots and scatter plots and convert visual data points into a structured numerical format."""
|
|
80
|
+
|
|
81
|
+
plots = FastMCP(
|
|
82
|
+
name="Axiomatic plots tools server",
|
|
83
|
+
instructions=PLOTS_SERVER_INSTRUCTIONS,
|
|
84
|
+
version="0.0.1",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@plots.tool(
|
|
89
|
+
name="extract_numerical_series_points",
|
|
90
|
+
description="Analyzes images of line and scatter plots to extract precise numerical data points from all series in the plot",
|
|
91
|
+
tags={"plot", "filesystem", "analyze"},
|
|
92
|
+
)
|
|
93
|
+
async def extract_data_from_plot_image(
|
|
94
|
+
plot_path: Annotated[Path, "The absolute path to the image file of the plot to analyze. Supports only PNG for now"],
|
|
95
|
+
max_number_points_per_series: Annotated[
|
|
96
|
+
int,
|
|
97
|
+
"Maximum points returned per series. Uses random sampling if plot contains more points than limit",
|
|
98
|
+
] = 100,
|
|
99
|
+
) -> Annotated[SeriesPointsData, "Extracted plot data containing series and points from the plot image"]:
|
|
100
|
+
if not plot_path.is_file():
|
|
101
|
+
raise FileNotFoundError(f"Image not found or is not a regular file: {plot_path}")
|
|
102
|
+
|
|
103
|
+
supported_extensions = {".png"}
|
|
104
|
+
file_extension = plot_path.suffix.lower()
|
|
105
|
+
if file_extension not in supported_extensions:
|
|
106
|
+
raise ValueError(f"Unsupported image format: {file_extension}. Supported formats: {', '.join(supported_extensions)}")
|
|
107
|
+
|
|
108
|
+
mime_type, _ = mimetypes.guess_type(str(plot_path))
|
|
109
|
+
if not mime_type or not mime_type.startswith("image/"):
|
|
110
|
+
mime_type = "application/octet-stream"
|
|
111
|
+
|
|
112
|
+
with Path.open(plot_path, "rb") as f:
|
|
113
|
+
files = {"plot_img": (plot_path.name, f, mime_type)}
|
|
114
|
+
params = {"get_img_coords": True, "v2": True}
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
response = AxiomaticAPIClient().post("/document/plot/points", files=files, params=params)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
raise ToolError(f"Failed to analyze plot image: {e!s}") from e
|
|
120
|
+
|
|
121
|
+
if not isinstance(response, dict):
|
|
122
|
+
raise ToolError("Upstream service returned non-JSON response")
|
|
123
|
+
|
|
124
|
+
if "extracted_series" not in response:
|
|
125
|
+
raise ToolError("Upstream service returned unexpected response format")
|
|
126
|
+
|
|
127
|
+
return process_plot_parser_output(response, max_points=max_number_points_per_series)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
API_URL = "https://api.axiomatic-ai.com"
|
|
7
|
+
TIMEOUT = 1000
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AxiomaticAPIClient:
|
|
11
|
+
def __init__(self):
|
|
12
|
+
api_key = os.getenv("AXIOMATIC_API_KEY")
|
|
13
|
+
if not api_key:
|
|
14
|
+
raise ValueError("AXIOMATIC_API_KEY environment variable is not set")
|
|
15
|
+
|
|
16
|
+
self.client = httpx.Client(
|
|
17
|
+
base_url=API_URL,
|
|
18
|
+
timeout=TIMEOUT,
|
|
19
|
+
headers={
|
|
20
|
+
"X-API-Key": api_key,
|
|
21
|
+
},
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def get(
|
|
25
|
+
self,
|
|
26
|
+
endpoint: str,
|
|
27
|
+
params: dict[str, Any] | None = None,
|
|
28
|
+
) -> dict[str, Any]:
|
|
29
|
+
response = self.client.get(endpoint, params=params)
|
|
30
|
+
response.raise_for_status()
|
|
31
|
+
return response.json()
|
|
32
|
+
|
|
33
|
+
def post(
|
|
34
|
+
self,
|
|
35
|
+
endpoint: str,
|
|
36
|
+
data: dict[str, Any] | None = None,
|
|
37
|
+
files: dict[str, Any] | None = None,
|
|
38
|
+
params: dict[str, Any] | None = None,
|
|
39
|
+
) -> dict[str, Any]:
|
|
40
|
+
response = (
|
|
41
|
+
self.client.post(endpoint, files=files, data=data, params=params) if files else self.client.post(endpoint, json=data, params=params)
|
|
42
|
+
)
|
|
43
|
+
response.raise_for_status()
|
|
44
|
+
return response.json()
|
|
45
|
+
|
|
46
|
+
def __enter__(self):
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
50
|
+
self.client.close()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
from ...shared.api_client import AxiomaticAPIClient
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ParseResponse(BaseModel):
|
|
10
|
+
markdown: str = Field(description="The extracted Markdown text, equations as latex, and images as base64 encoded strings.")
|
|
11
|
+
images: dict[str, str] = Field(default_factory=dict, description="Images as base64 encoded strings")
|
|
12
|
+
interline_equations: list[str] = Field(default_factory=list, description="Interline equations as latex")
|
|
13
|
+
inline_equations: list[str] = Field(
|
|
14
|
+
default_factory=list,
|
|
15
|
+
description="Inline equations as latex",
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def pdf_to_markdown(file_path: Path) -> ParseResponse:
|
|
20
|
+
if not file_path.exists():
|
|
21
|
+
raise FileNotFoundError(f"Document not found: {file_path}")
|
|
22
|
+
|
|
23
|
+
if file_path.suffix.lower() != ".pdf":
|
|
24
|
+
raise ValueError("File must be a PDF")
|
|
25
|
+
|
|
26
|
+
file_content = await asyncio.to_thread(file_path.read_bytes)
|
|
27
|
+
files = {"file": (file_path.name, file_content, "application/pdf")}
|
|
28
|
+
data = {"method": "mistral", "ocr": False, "layout_model": "doclayout_yolo"}
|
|
29
|
+
|
|
30
|
+
response = await asyncio.to_thread(
|
|
31
|
+
AxiomaticAPIClient().post,
|
|
32
|
+
"/document/parse",
|
|
33
|
+
files=files,
|
|
34
|
+
data=data,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return ParseResponse(**response)
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: axiomatic-mcp
|
|
3
|
+
Version: 0.0a3
|
|
4
|
+
Summary: Modular MCP servers for Axiomatic_AI
|
|
5
|
+
Author-email: Axiomatic Team <developers@axiomatic.ai>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/axiomatic/ax-mcp
|
|
8
|
+
Project-URL: Issues, https://github.com/axiomatic/ax-mcp/issues
|
|
9
|
+
Keywords: mcp,axiomatic,ai,fastmcp
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: fastmcp>=0.1.0
|
|
21
|
+
Requires-Dist: pydantic>=2.0.0
|
|
22
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
23
|
+
Requires-Dist: httpx>=0.25.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
26
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
29
|
+
|
|
30
|
+
# Axiomatic MCP Servers
|
|
31
|
+
|
|
32
|
+
MCP (Model Context Protocol) servers that provide AI assistants with access to the Axiomatic_AI Platform - a suite of advanced tools for scientific computing, document processing, and photonic circuit design.
|
|
33
|
+
|
|
34
|
+
## Available Servers
|
|
35
|
+
|
|
36
|
+
### 📄 [Documents Server](./axiomatic_mcp/servers/documents/)
|
|
37
|
+
|
|
38
|
+
Convert PDF documents to markdown with advanced OCR and layout understanding.
|
|
39
|
+
|
|
40
|
+
### 🖌️ [Equations Server](./axiomatic_mcp/servers/equations/)
|
|
41
|
+
|
|
42
|
+
Compose equation of your interest based on information in the scientific paper.
|
|
43
|
+
|
|
44
|
+
### 🔬 [PIC Designer Server](./axiomatic_mcp/servers/pic/)
|
|
45
|
+
|
|
46
|
+
Design photonic integrated circuits using natural language descriptions.
|
|
47
|
+
|
|
48
|
+
### 📊 [Plots Server](./axiomatic_mcp/servers/plots/)
|
|
49
|
+
|
|
50
|
+
Extract numerical data from plot images for analysis and reproduction.
|
|
51
|
+
|
|
52
|
+
### 🖥️ [Code Execution Server](./axiomatic_mcp/servers/code_execution/)
|
|
53
|
+
|
|
54
|
+
Execute Python code in a secure environment with support for selected libraries (`gdsfactory`, `z3`, `json`).
|
|
55
|
+
Useful for photonic design workflows, symbolic reasoning, and structured data manipulation.
|
|
56
|
+
|
|
57
|
+
## Getting an API Key
|
|
58
|
+
|
|
59
|
+
All Axiomatic MCP servers require an API key:
|
|
60
|
+
|
|
61
|
+
1. Contact developers@axiomatic-ai.com to request access
|
|
62
|
+
2. Add the API key to your MCP client configuration as `AXIOMATIC_API_KEY`
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
Installation instructions can be found for each specific server in their README.
|
|
67
|
+
|
|
68
|
+
### Setting up MCP Servers in AI Clients
|
|
69
|
+
|
|
70
|
+
#### Claude Desktop
|
|
71
|
+
|
|
72
|
+
1. Open Claude Desktop settings
|
|
73
|
+
2. Navigate to Developer → Edit MCP config
|
|
74
|
+
3. Add the server configuration(s) above
|
|
75
|
+
4. Restart Claude Desktop
|
|
76
|
+
|
|
77
|
+
#### Cursor
|
|
78
|
+
|
|
79
|
+
1. Open Cursor settings (Cmd/Ctrl + ,)
|
|
80
|
+
2. Search for "MCP"
|
|
81
|
+
3. Add the server configuration(s) to the MCP settings
|
|
82
|
+
4. Restart Cursor
|
|
83
|
+
|
|
84
|
+
#### Other MCP Clients
|
|
85
|
+
|
|
86
|
+
Refer to your client's documentation for MCP server configuration.
|
|
87
|
+
|
|
88
|
+
## Development
|
|
89
|
+
|
|
90
|
+
### Local Development Setup
|
|
91
|
+
|
|
92
|
+
1. Clone the repository:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
git clone https://github.com/axiomatic/ax-mcp.git
|
|
96
|
+
cd ax-mcp
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
2. Install in development mode:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
make install-dev
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
3. Configure your MCP client to use local Python modules:
|
|
106
|
+
|
|
107
|
+
> See specific MCP server README for specific installation instructions.
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"axiomatic-documents": {
|
|
112
|
+
"command": "python",
|
|
113
|
+
"args": ["-m", "axiomatic_mcp.servers.documents"],
|
|
114
|
+
"env": {
|
|
115
|
+
"AXIOMATIC_API_KEY": "your-api-key-here"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Adding a New Server
|
|
122
|
+
|
|
123
|
+
1. Create server directory:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
mkdir axiomatic_mcp/servers/my_domain
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
2. Create `__init__.py`:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from .server import MyDomainServer
|
|
133
|
+
|
|
134
|
+
def main():
|
|
135
|
+
server = MyDomainServer()
|
|
136
|
+
server.run()
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
2. Create `__main__.py`:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from . import main
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
main()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
3. Implement server in `server.py`:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from fastmcp import FastMCP
|
|
152
|
+
|
|
153
|
+
mcp = FastMCP(
|
|
154
|
+
name="NAME",
|
|
155
|
+
instructions="""GIVE NICE INSTRUCTIONS""",
|
|
156
|
+
version="0.0.1",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
@mcp.tool(
|
|
160
|
+
name="tool_name",
|
|
161
|
+
description="DESCRIPTION",
|
|
162
|
+
tags=["TAG"],
|
|
163
|
+
)
|
|
164
|
+
def my_tool():
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
# Add more tools as needed
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
4. Add entry point to `pyproject.toml`:
|
|
171
|
+
|
|
172
|
+
```toml
|
|
173
|
+
[project.scripts]
|
|
174
|
+
axiomatic-mydomain = "axiomatic_mcp.servers.my_domain:main"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
5. Update README.md with instructions on installing your server. You can generate the "Add to cursor" button [here](https://docs.cursor.com/en/tools/developers)
|
|
178
|
+
|
|
179
|
+
6. Don't forget to link to your server's README.md in the main project README.md
|
|
180
|
+
|
|
181
|
+
### Release Process
|
|
182
|
+
|
|
183
|
+
#### Publishing a Release
|
|
184
|
+
|
|
185
|
+
1. Create a new release branch
|
|
186
|
+
1. Update version in `pyproject.toml`
|
|
187
|
+
1. Commit and push changes
|
|
188
|
+
1. Create a pull request titled "Release: YOUR FEATURE(s)". Include detailed description of what's included in the release.
|
|
189
|
+
1. Create a GitHub release with tag `vX.Y.Z`
|
|
190
|
+
1. GitHub Actions automatically publishes to PyPI
|
|
191
|
+
|
|
192
|
+
The package is available at: https://pypi.org/project/axiomatic-mcp/
|
|
193
|
+
|
|
194
|
+
## Contributing
|
|
195
|
+
|
|
196
|
+
We welcome contributions! To add a new server or improve existing ones:
|
|
197
|
+
|
|
198
|
+
1. Fork the repository
|
|
199
|
+
2. Create a feature branch
|
|
200
|
+
3. Implement your changes following the existing patterns
|
|
201
|
+
4. Add documentation to your server directory
|
|
202
|
+
5. Submit a pull request
|
|
203
|
+
|
|
204
|
+
For detailed guidelines on adding new servers, see the [Development](#development) section.
|
|
205
|
+
|
|
206
|
+
## Troubleshooting
|
|
207
|
+
|
|
208
|
+
### Server not appearing in Cursor
|
|
209
|
+
|
|
210
|
+
1. Restart Cursor after updating MCP settings
|
|
211
|
+
2. Check the Output panel (View → Output → MCP) for errors
|
|
212
|
+
3. Verify the command path is correct
|
|
213
|
+
|
|
214
|
+
### Multiple servers overwhelming the LLM
|
|
215
|
+
|
|
216
|
+
Install only the domain servers you need. Each server runs independently, so you can add/remove them as needed.
|
|
217
|
+
|
|
218
|
+
### API connection errors
|
|
219
|
+
|
|
220
|
+
1. Verify your API key is set correctly
|
|
221
|
+
2. Check internet connection
|
|
222
|
+
|
|
223
|
+
## Support
|
|
224
|
+
|
|
225
|
+
- **Issues**: [GitHub Issues](https://github.com/axiomatic/ax-mcp/issues)
|
|
226
|
+
- **Email**: developers@axiomatic-ai.com
|
|
227
|
+
|
|
228
|
+
## Creating >>Add to Cursor<< button:
|
|
229
|
+
|
|
230
|
+
Copy your MCP client configuration and paste it there:
|
|
231
|
+
|
|
232
|
+
https://docs.cursor.com/en/tools/developers#generate-install-link
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
axiomatic_mcp/__init__.py
|
|
4
|
+
axiomatic_mcp.egg-info/PKG-INFO
|
|
5
|
+
axiomatic_mcp.egg-info/SOURCES.txt
|
|
6
|
+
axiomatic_mcp.egg-info/dependency_links.txt
|
|
7
|
+
axiomatic_mcp.egg-info/entry_points.txt
|
|
8
|
+
axiomatic_mcp.egg-info/requires.txt
|
|
9
|
+
axiomatic_mcp.egg-info/top_level.txt
|
|
10
|
+
axiomatic_mcp/servers/__init__.py
|
|
11
|
+
axiomatic_mcp/servers/code_execution/__init__.py
|
|
12
|
+
axiomatic_mcp/servers/code_execution/__main__.py
|
|
13
|
+
axiomatic_mcp/servers/code_execution/server.py
|
|
14
|
+
axiomatic_mcp/servers/documents/__init__.py
|
|
15
|
+
axiomatic_mcp/servers/documents/__main__.py
|
|
16
|
+
axiomatic_mcp/servers/documents/server.py
|
|
17
|
+
axiomatic_mcp/servers/equations/__init__.py
|
|
18
|
+
axiomatic_mcp/servers/equations/__main__.py
|
|
19
|
+
axiomatic_mcp/servers/equations/server.py
|
|
20
|
+
axiomatic_mcp/servers/pic/__init__.py
|
|
21
|
+
axiomatic_mcp/servers/pic/__main__.py
|
|
22
|
+
axiomatic_mcp/servers/pic/server.py
|
|
23
|
+
axiomatic_mcp/servers/plots/__init__.py
|
|
24
|
+
axiomatic_mcp/servers/plots/__main__.py
|
|
25
|
+
axiomatic_mcp/servers/plots/server.py
|
|
26
|
+
axiomatic_mcp/shared/__init__.py
|
|
27
|
+
axiomatic_mcp/shared/api_client.py
|
|
28
|
+
axiomatic_mcp/shared/documents/pdf_to_markdown.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
axiomatic-code-execution = axiomatic_mcp.servers.code_execution:main
|
|
3
|
+
axiomatic-documents = axiomatic_mcp.servers.documents:main
|
|
4
|
+
axiomatic-equations = axiomatic_mcp.servers.equations:main
|
|
5
|
+
axiomatic-pic = axiomatic_mcp.servers.pic:main
|
|
6
|
+
axiomatic-plots = axiomatic_mcp.servers.plots:main
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
axiomatic_mcp
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "axiomatic-mcp"
|
|
7
|
+
version = "0.0.alpha3"
|
|
8
|
+
description = "Modular MCP servers for Axiomatic_AI"
|
|
9
|
+
authors = [{name = "Axiomatic Team", email = "developers@axiomatic.ai"}]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
|
+
]
|
|
23
|
+
keywords = ["mcp", "axiomatic", "ai", "fastmcp"]
|
|
24
|
+
urls = {Homepage = "https://github.com/axiomatic/ax-mcp", Issues = "https://github.com/axiomatic/ax-mcp/issues"}
|
|
25
|
+
dependencies = [
|
|
26
|
+
"fastmcp>=0.1.0",
|
|
27
|
+
"pydantic>=2.0.0",
|
|
28
|
+
"python-dotenv>=1.0.0",
|
|
29
|
+
"httpx>=0.25.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=7.0.0",
|
|
35
|
+
"black>=23.0.0",
|
|
36
|
+
"ruff>=0.1.0",
|
|
37
|
+
"mypy>=1.0.0",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
axiomatic-pic = "axiomatic_mcp.servers.pic:main"
|
|
42
|
+
axiomatic-code-execution = "axiomatic_mcp.servers.code_execution:main"
|
|
43
|
+
axiomatic-documents = "axiomatic_mcp.servers.documents:main"
|
|
44
|
+
axiomatic-plots = "axiomatic_mcp.servers.plots:main"
|
|
45
|
+
axiomatic-equations = "axiomatic_mcp.servers.equations:main"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["."]
|
|
49
|
+
include = ["axiomatic_mcp*"]
|
|
50
|
+
|
|
51
|
+
[tool.black]
|
|
52
|
+
line-length = 150
|
|
53
|
+
target-version = ["py310", "py311", "py312"]
|
|
54
|
+
|
|
55
|
+
[tool.ruff]
|
|
56
|
+
line-length = 150
|
|
57
|
+
target-version = "py310"
|
|
58
|
+
select = ["E", "F", "I", "N", "UP", "B", "C4", "PTH", "SIM", "RUF"]
|
|
59
|
+
|
|
60
|
+
[tool.mypy]
|
|
61
|
+
python_version = "3.10"
|
|
62
|
+
strict = true
|
|
63
|
+
warn_return_any = true
|
|
64
|
+
warn_unused_configs = true
|