d365fo-agent-developer 0.6.0__tar.gz → 0.6.2__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.
- {d365fo_agent_developer-0.6.0/src/d365fo_agent_developer.egg-info → d365fo_agent_developer-0.6.2}/PKG-INFO +19 -13
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/README.md +146 -140
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/pyproject.toml +59 -57
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/knowledge_fetch.py +70 -70
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/mcp_server.py +10 -4
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2/src/d365fo_agent_developer.egg-info}/PKG-INFO +19 -13
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent_developer.egg-info/entry_points.txt +1 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_mcp_toolkit.py +1 -1
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/LICENSE +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/setup.cfg +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/__init__.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/aot_relations.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/build.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/cli.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/data/aot-type-profiles.json +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/data/x++-methodology.md +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/data/x++-rules.json +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/entity_derive.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/generator.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/graph_query.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/graphify_runner.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/index_store.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/indexer.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/knowledge.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/linter.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/models.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/packageslocal_export.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/rules.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/security_wiring.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/specs.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/sql_model.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/type_profile.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/validate.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent_developer.egg-info/SOURCES.txt +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent_developer.egg-info/dependency_links.txt +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent_developer.egg-info/requires.txt +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent_developer.egg-info/top_level.txt +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_aot_relations.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_build.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_catalog.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_cli.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_entity_derive.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_linter.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_security_wiring.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_spec_pipeline.py +0 -0
- {d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/tests/test_sql_model.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: d365fo-agent-developer
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: Local D365 F&O knowledge toolkit: corpus indexing (SQLite FTS5), deterministic generation, and an MCP server that grounds coding agents (Claude Code, Codex) in real AOT facts.
|
|
5
5
|
Author-email: David Bru <dbru@fiveforty.fr>
|
|
6
6
|
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/dbru540/d365fo-agent
|
|
8
|
-
Project-URL: Repository, https://github.com/dbru540/d365fo-agent
|
|
9
|
-
Project-URL: Issues, https://github.com/dbru540/d365fo-agent/issues
|
|
7
|
+
Project-URL: Homepage, https://github.com/dbru540/d365fo-agent-developer
|
|
8
|
+
Project-URL: Repository, https://github.com/dbru540/d365fo-agent-developer
|
|
9
|
+
Project-URL: Issues, https://github.com/dbru540/d365fo-agent-developer/issues
|
|
10
10
|
Keywords: dynamics-365,d365fo,x++,aot,mcp,model-context-protocol,claude,claude-code,codex,ai,code-generation,rag
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -29,7 +29,7 @@ Requires-Dist: ruff; extra == "dev"
|
|
|
29
29
|
Requires-Dist: build; extra == "dev"
|
|
30
30
|
Dynamic: license-file
|
|
31
31
|
|
|
32
|
-
# d365fo-agent — D365 F&O X++ knowledge for Claude Code & Codex
|
|
32
|
+
# d365fo-agent-developer — D365 F&O X++ knowledge for Claude Code & Codex
|
|
33
33
|
|
|
34
34
|
A local **MCP server** that gives an AI coding agent (Claude Code, Codex, any MCP host) a grounded
|
|
35
35
|
**knowledge base of Dynamics 365 Finance & Operations X++** — so you can develop for D365 quickly
|
|
@@ -51,9 +51,14 @@ compiler.
|
|
|
51
51
|
```bash
|
|
52
52
|
pip install d365fo-agent-developer
|
|
53
53
|
# or, isolated: pipx install d365fo-agent-developer
|
|
54
|
+
# or zero-install, straight from PyPI at launch time: uvx d365fo-agent-developer
|
|
54
55
|
```
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
With `uvx` you can even skip the install entirely — point your MCP client at
|
|
58
|
+
`uvx` with args `["d365fo-agent-developer"]` (e.g. in Claude Desktop's
|
|
59
|
+
`claude_desktop_config.json`) and the latest published server runs on demand.
|
|
60
|
+
|
|
61
|
+
This installs two commands: `d365fo-agent-developer` (the MCP server; `d365fo-mcp` is a short alias) and `d365fo-agent` (the CLI).
|
|
57
62
|
|
|
58
63
|
## Get the knowledge base (once)
|
|
59
64
|
|
|
@@ -84,18 +89,18 @@ d365fo-agent build-index \
|
|
|
84
89
|
```json
|
|
85
90
|
{
|
|
86
91
|
"mcpServers": {
|
|
87
|
-
"d365fo": { "command": "d365fo-
|
|
92
|
+
"d365fo-agent-developer": { "command": "d365fo-agent-developer", "args": [] }
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
```
|
|
91
96
|
|
|
92
|
-
…or one command: `claude mcp add d365fo d365fo-
|
|
97
|
+
…or one command: `claude mcp add d365fo-agent-developer d365fo-agent-developer`
|
|
93
98
|
|
|
94
99
|
**Codex** — add to `~/.codex/config.toml`:
|
|
95
100
|
|
|
96
101
|
```toml
|
|
97
|
-
[mcp_servers.d365fo]
|
|
98
|
-
command = "d365fo-
|
|
102
|
+
[mcp_servers.d365fo-agent-developer]
|
|
103
|
+
command = "d365fo-agent-developer"
|
|
99
104
|
args = []
|
|
100
105
|
```
|
|
101
106
|
|
|
@@ -109,8 +114,8 @@ Point the server at your D365 source repo so your **custom** classes/tables/EDTs
|
|
|
109
114
|
are indexed too, and so the rich tools can read real signatures and clone real examples:
|
|
110
115
|
|
|
111
116
|
```toml
|
|
112
|
-
[mcp_servers.d365fo]
|
|
113
|
-
command = "d365fo-
|
|
117
|
+
[mcp_servers.d365fo-agent-developer]
|
|
118
|
+
command = "d365fo-agent-developer"
|
|
114
119
|
args = ["--repo-root", "C:/path/to/your/D365Repo",
|
|
115
120
|
"--rules", "C:/path/to/your/rules.json",
|
|
116
121
|
"--packages-root", "C:/AOSService/PackagesLocalDirectory"]
|
|
@@ -127,7 +132,8 @@ args = ["--repo-root", "C:/path/to/your/D365Repo",
|
|
|
127
132
|
`element_exists`, `find_element`, `search_corpus`, `get_signature`, `get_extension_chain`,
|
|
128
133
|
`get_security_links`, `get_entity_exposure`, `find_similar_examples`, `scaffold_object`,
|
|
129
134
|
`find_references`, `find_reverse_references`, `analyze_spec`, `generate_from_spec`, `validate_xml`,
|
|
130
|
-
`lint_artifact`, `derive_entity`, `wire_security`, `compile_model`, `
|
|
135
|
+
`lint_artifact`, `derive_entity`, `wire_security`, `compile_model`, `compile_generated`,
|
|
136
|
+
`get_sql_model`, `explore_functional_unit`, `find_relations`, `get_methodology`, `index_stats`.
|
|
131
137
|
|
|
132
138
|
See [docs/mcp-server.md](docs/mcp-server.md) for the verify-driven workflow and
|
|
133
139
|
[docs/x++-methodology.md](docs/x++-methodology.md) for the behavioural contract.
|
|
@@ -1,140 +1,146 @@
|
|
|
1
|
-
# d365fo-agent — D365 F&O X++ knowledge for Claude Code & Codex
|
|
2
|
-
|
|
3
|
-
A local **MCP server** that gives an AI coding agent (Claude Code, Codex, any MCP host) a grounded
|
|
4
|
-
**knowledge base of Dynamics 365 Finance & Operations X++** — so you can develop for D365 quickly
|
|
5
|
-
**without re-feeding a whole repo for analysis every time**.
|
|
6
|
-
|
|
7
|
-
It grounds the agent in real AOT facts: it verifies that a class/table/EDT/enum/entity actually
|
|
8
|
-
exists (anti-hallucination), searches the corpus, walks extension/security relationships, serves an
|
|
9
|
-
X++ engineering methodology, validates generated XML against learned per-type structure, scaffolds
|
|
10
|
-
or deterministically generates artifacts, and (on a Windows D365 host) compiles with the real X++
|
|
11
|
-
compiler.
|
|
12
|
-
|
|
13
|
-
- **Pure Python standard library** — zero runtime dependencies, runs anywhere Python 3.11+ runs.
|
|
14
|
-
- **Vendor-neutral** — Claude Code, Codex, Gemini CLI, or any MCP-speaking client over stdio.
|
|
15
|
-
- The standard D365 corpus is the same for everyone, so it is indexed **once** and used as a
|
|
16
|
-
portable knowledge base; your own custom code is **optional**.
|
|
17
|
-
|
|
18
|
-
## Install
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
pip install d365fo-agent-developer
|
|
22
|
-
# or, isolated: pipx install d365fo-agent-developer
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
d365fo-agent
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
1
|
+
# d365fo-agent-developer — D365 F&O X++ knowledge for Claude Code & Codex
|
|
2
|
+
|
|
3
|
+
A local **MCP server** that gives an AI coding agent (Claude Code, Codex, any MCP host) a grounded
|
|
4
|
+
**knowledge base of Dynamics 365 Finance & Operations X++** — so you can develop for D365 quickly
|
|
5
|
+
**without re-feeding a whole repo for analysis every time**.
|
|
6
|
+
|
|
7
|
+
It grounds the agent in real AOT facts: it verifies that a class/table/EDT/enum/entity actually
|
|
8
|
+
exists (anti-hallucination), searches the corpus, walks extension/security relationships, serves an
|
|
9
|
+
X++ engineering methodology, validates generated XML against learned per-type structure, scaffolds
|
|
10
|
+
or deterministically generates artifacts, and (on a Windows D365 host) compiles with the real X++
|
|
11
|
+
compiler.
|
|
12
|
+
|
|
13
|
+
- **Pure Python standard library** — zero runtime dependencies, runs anywhere Python 3.11+ runs.
|
|
14
|
+
- **Vendor-neutral** — Claude Code, Codex, Gemini CLI, or any MCP-speaking client over stdio.
|
|
15
|
+
- The standard D365 corpus is the same for everyone, so it is indexed **once** and used as a
|
|
16
|
+
portable knowledge base; your own custom code is **optional**.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install d365fo-agent-developer
|
|
22
|
+
# or, isolated: pipx install d365fo-agent-developer
|
|
23
|
+
# or zero-install, straight from PyPI at launch time: uvx d365fo-agent-developer
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
With `uvx` you can even skip the install entirely — point your MCP client at
|
|
27
|
+
`uvx` with args `["d365fo-agent-developer"]` (e.g. in Claude Desktop's
|
|
28
|
+
`claude_desktop_config.json`) and the latest published server runs on demand.
|
|
29
|
+
|
|
30
|
+
This installs two commands: `d365fo-agent-developer` (the MCP server; `d365fo-mcp` is a short alias) and `d365fo-agent` (the CLI).
|
|
31
|
+
|
|
32
|
+
## Get the knowledge base (once)
|
|
33
|
+
|
|
34
|
+
Pick one. Both produce a local index at `~/.d365fo-agent/d365fo.db` that the server uses by default.
|
|
35
|
+
|
|
36
|
+
**A. Download the prebuilt standard-D365 index** (fastest, no D365 install needed):
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
d365fo-agent fetch-knowledge # downloads + caches the standard knowledge index
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**B. Build it from your own D365 dev box** (no download; uses metadata you already have):
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
d365fo-agent build-index \
|
|
46
|
+
--db ~/.d365fo-agent/d365fo.db \
|
|
47
|
+
--packages-root "C:/AOSService/PackagesLocalDirectory" \
|
|
48
|
+
--rebuild
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
> The methodology, default lint rules, and a default learned type-profile ship **inside** the
|
|
52
|
+
> package, so validation and guidance work out of the box even before the index is built.
|
|
53
|
+
|
|
54
|
+
## Wire it into your agent
|
|
55
|
+
|
|
56
|
+
**Claude Code** — add to `.mcp.json` (project) or `~/.claude.json` (global):
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"mcpServers": {
|
|
61
|
+
"d365fo-agent-developer": { "command": "d365fo-agent-developer", "args": [] }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
…or one command: `claude mcp add d365fo-agent-developer d365fo-agent-developer`
|
|
67
|
+
|
|
68
|
+
**Codex** — add to `~/.codex/config.toml`:
|
|
69
|
+
|
|
70
|
+
```toml
|
|
71
|
+
[mcp_servers.d365fo-agent-developer]
|
|
72
|
+
command = "d365fo-agent-developer"
|
|
73
|
+
args = []
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
With no `--db`, the server uses the cached knowledge index automatically. That's it — ask the agent
|
|
77
|
+
to build something for D365 and it will verify elements, follow the methodology, and validate its
|
|
78
|
+
output instead of guessing.
|
|
79
|
+
|
|
80
|
+
## Add your custom code (optional)
|
|
81
|
+
|
|
82
|
+
Point the server at your D365 source repo so your **custom** classes/tables/EDTs/enums/extensions
|
|
83
|
+
are indexed too, and so the rich tools can read real signatures and clone real examples:
|
|
84
|
+
|
|
85
|
+
```toml
|
|
86
|
+
[mcp_servers.d365fo-agent-developer]
|
|
87
|
+
command = "d365fo-agent-developer"
|
|
88
|
+
args = ["--repo-root", "C:/path/to/your/D365Repo",
|
|
89
|
+
"--rules", "C:/path/to/your/rules.json",
|
|
90
|
+
"--packages-root", "C:/AOSService/PackagesLocalDirectory"]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
| Capability | Knowledge index only | + a PackagesLocalDirectory / repo |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| Verify an element exists, search, relations, methodology, validation, scaffolding by template | ✅ | ✅ |
|
|
96
|
+
| Read a real signature, clone a real example (`get_signature`, `find_similar_examples`, `scaffold_object`) | needs source files | ✅ |
|
|
97
|
+
| Compile with the real X++ compiler (`compile_model`) | — | ✅ (Windows D365 host) |
|
|
98
|
+
|
|
99
|
+
## What the agent gets (MCP tools)
|
|
100
|
+
|
|
101
|
+
`element_exists`, `find_element`, `search_corpus`, `get_signature`, `get_extension_chain`,
|
|
102
|
+
`get_security_links`, `get_entity_exposure`, `find_similar_examples`, `scaffold_object`,
|
|
103
|
+
`find_references`, `find_reverse_references`, `analyze_spec`, `generate_from_spec`, `validate_xml`,
|
|
104
|
+
`lint_artifact`, `derive_entity`, `wire_security`, `compile_model`, `compile_generated`,
|
|
105
|
+
`get_sql_model`, `explore_functional_unit`, `find_relations`, `get_methodology`, `index_stats`.
|
|
106
|
+
|
|
107
|
+
See [docs/mcp-server.md](docs/mcp-server.md) for the verify-driven workflow and
|
|
108
|
+
[docs/x++-methodology.md](docs/x++-methodology.md) for the behavioural contract.
|
|
109
|
+
|
|
110
|
+
## Maintainer: publish the knowledge index
|
|
111
|
+
|
|
112
|
+
The wheel stays tiny; the ~100 MB standard index is distributed as a downloadable asset.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# 1. Build a STANDARD-only index from a PackagesLocalDirectory (no custom repo)
|
|
116
|
+
d365fo-agent build-index --db d365fo-standard.db --packages-root <PLD> --rebuild
|
|
117
|
+
# 2. (optional) learn type profiles to ship as the default
|
|
118
|
+
d365fo-agent build-type-profiles --db d365fo-standard.db --packages-root <PLD> \
|
|
119
|
+
--out src/d365fo_agent/data/aot-type-profiles.json
|
|
120
|
+
# 3. Compress and attach to a GitHub release
|
|
121
|
+
python -c "import gzip,shutil; shutil.copyfileobj(open('d365fo-standard.db','rb'), gzip.open('d365fo-standard.db.gz','wb'))"
|
|
122
|
+
# 4. Point users at it: set DEFAULT_KNOWLEDGE_URL in knowledge_fetch.py (or pass --url)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> **Note:** the index holds factual AOT metadata (element names, types, packages, labels,
|
|
126
|
+
> relations) — not Microsoft source. Confirm your redistribution position before publishing a
|
|
127
|
+
> prebuilt standard index; option **B** above lets each user build their own with zero redistribution.
|
|
128
|
+
|
|
129
|
+
To publish the package itself: `python -m build` then `python -m twine upload dist/*` (PyPI account
|
|
130
|
+
required).
|
|
131
|
+
|
|
132
|
+
## Develop / contribute
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
pip install -e ".[dev]"
|
|
136
|
+
PYTHONPATH=src python -m unittest discover -s tests # full test suite
|
|
137
|
+
ruff check src/d365fo_agent tests
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Docs: [Architecture](docs/architecture.md) · [MCP Server](docs/mcp-server.md) ·
|
|
141
|
+
[X++ Methodology](docs/x++-methodology.md) · [Specification Contract](docs/specification-contract.md) ·
|
|
142
|
+
[Metadata Schema](docs/metadata-schema.md) · [Tool Catalog](docs/tool-catalog.md)
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -1,57 +1,59 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=61"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "d365fo-agent-developer"
|
|
7
|
-
version = "0.6.
|
|
8
|
-
description = "Local D365 F&O knowledge toolkit: corpus indexing (SQLite FTS5), deterministic generation, and an MCP server that grounds coding agents (Claude Code, Codex) in real AOT facts."
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.11"
|
|
11
|
-
license = { text = "MIT" }
|
|
12
|
-
authors = [{ name = "David Bru", email = "dbru@fiveforty.fr" }]
|
|
13
|
-
keywords = [
|
|
14
|
-
"dynamics-365", "d365fo", "x++", "aot", "mcp", "model-context-protocol",
|
|
15
|
-
"claude", "claude-code", "codex", "ai", "code-generation", "rag",
|
|
16
|
-
]
|
|
17
|
-
classifiers = [
|
|
18
|
-
"Development Status :: 4 - Beta",
|
|
19
|
-
"Intended Audience :: Developers",
|
|
20
|
-
"License :: OSI Approved :: MIT License",
|
|
21
|
-
"Operating System :: OS Independent",
|
|
22
|
-
"Programming Language :: Python :: 3",
|
|
23
|
-
"Programming Language :: Python :: 3.11",
|
|
24
|
-
"Programming Language :: Python :: 3.12",
|
|
25
|
-
"Programming Language :: Python :: 3.13",
|
|
26
|
-
"Topic :: Software Development :: Code Generators",
|
|
27
|
-
"Topic :: Software Development :: Build Tools",
|
|
28
|
-
]
|
|
29
|
-
# Standard library only — nothing to install at runtime, which keeps the MCP server portable.
|
|
30
|
-
dependencies = []
|
|
31
|
-
|
|
32
|
-
[project.urls]
|
|
33
|
-
Homepage = "https://github.com/dbru540/d365fo-agent"
|
|
34
|
-
Repository = "https://github.com/dbru540/d365fo-agent"
|
|
35
|
-
Issues = "https://github.com/dbru540/d365fo-agent/issues"
|
|
36
|
-
|
|
37
|
-
[project.optional-dependencies]
|
|
38
|
-
# The graph-building engine is the ONLY external dependency, and only the
|
|
39
|
-
# `run-graphify-staging` command needs it. Everything else (indexing, generation,
|
|
40
|
-
# MCP server, validation) is Python standard library only.
|
|
41
|
-
graph = ["graphify"]
|
|
42
|
-
dev = ["pytest", "ruff", "build"]
|
|
43
|
-
|
|
44
|
-
[project.scripts]
|
|
45
|
-
d365fo-agent = "d365fo_agent.cli:main"
|
|
46
|
-
d365fo-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
[
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "d365fo-agent-developer"
|
|
7
|
+
version = "0.6.2"
|
|
8
|
+
description = "Local D365 F&O knowledge toolkit: corpus indexing (SQLite FTS5), deterministic generation, and an MCP server that grounds coding agents (Claude Code, Codex) in real AOT facts."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "David Bru", email = "dbru@fiveforty.fr" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"dynamics-365", "d365fo", "x++", "aot", "mcp", "model-context-protocol",
|
|
15
|
+
"claude", "claude-code", "codex", "ai", "code-generation", "rag",
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Software Development :: Code Generators",
|
|
27
|
+
"Topic :: Software Development :: Build Tools",
|
|
28
|
+
]
|
|
29
|
+
# Standard library only — nothing to install at runtime, which keeps the MCP server portable.
|
|
30
|
+
dependencies = []
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/dbru540/d365fo-agent-developer"
|
|
34
|
+
Repository = "https://github.com/dbru540/d365fo-agent-developer"
|
|
35
|
+
Issues = "https://github.com/dbru540/d365fo-agent-developer/issues"
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
# The graph-building engine is the ONLY external dependency, and only the
|
|
39
|
+
# `run-graphify-staging` command needs it. Everything else (indexing, generation,
|
|
40
|
+
# MCP server, validation) is Python standard library only.
|
|
41
|
+
graph = ["graphify"]
|
|
42
|
+
dev = ["pytest", "ruff", "build"]
|
|
43
|
+
|
|
44
|
+
[project.scripts]
|
|
45
|
+
d365fo-agent = "d365fo_agent.cli:main"
|
|
46
|
+
d365fo-agent-developer = "d365fo_agent.mcp_server:main"
|
|
47
|
+
# Kept as a short alias of d365fo-agent-developer.
|
|
48
|
+
d365fo-mcp = "d365fo_agent.mcp_server:main"
|
|
49
|
+
|
|
50
|
+
[tool.setuptools]
|
|
51
|
+
package-dir = { "" = "src" }
|
|
52
|
+
|
|
53
|
+
[tool.setuptools.packages.find]
|
|
54
|
+
where = ["src"]
|
|
55
|
+
|
|
56
|
+
[tool.setuptools.package-data]
|
|
57
|
+
# Methodology, default lint rules, and a default learned type-profile ship inside the package so
|
|
58
|
+
# the server works after a plain `pip install` (no source tree needed).
|
|
59
|
+
d365fo_agent = ["data/*"]
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/knowledge_fetch.py
RENAMED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
"""Download a prebuilt standard-D365 knowledge index into the local cache.
|
|
2
|
-
|
|
3
|
-
This is what lets the MCP server help with X++ development WITHOUT the user re-indexing a full
|
|
4
|
-
repo every time: the standard D365 corpus is the same for everyone, so it is indexed once and
|
|
5
|
-
published as a release asset. ``fetch-knowledge`` downloads it to ``~/.d365fo-agent/d365fo.db``
|
|
6
|
-
(a ``.gz`` asset is decompressed on the fly). The user's own custom code stays optional
|
|
7
|
-
(``--repo-root``). Standard-library only (``urllib`` + ``gzip``).
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
import gzip
|
|
13
|
-
import shutil
|
|
14
|
-
import urllib.request
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
|
|
17
|
-
# Published location of the standard-D365 knowledge index (a SQLite .db or .db.gz). The asset is
|
|
18
|
-
# decoupled from the code version (tag `knowledge-v1`) so wheel releases don't re-upload 100 MB.
|
|
19
|
-
# Override with --url, or build your own from a PLD when the asset is unavailable.
|
|
20
|
-
DEFAULT_KNOWLEDGE_URL = (
|
|
21
|
-
"https://github.com/dbru540/d365fo-agent/releases/download/knowledge-v1/d365fo-standard.db.gz"
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def _is_gzip(path: Path) -> bool:
|
|
26
|
-
with open(path, "rb") as handle:
|
|
27
|
-
return handle.read(2) == b"\x1f\x8b"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def fetch_knowledge(
|
|
31
|
-
url: str | None = None,
|
|
32
|
-
dest: str | Path | None = None,
|
|
33
|
-
*,
|
|
34
|
-
force: bool = False,
|
|
35
|
-
opener=urllib.request.urlopen,
|
|
36
|
-
) -> dict[str, object]:
|
|
37
|
-
"""Download the knowledge index to ``dest`` (default: the local cache). Returns a result dict.
|
|
38
|
-
|
|
39
|
-
``opener`` is injectable for testing. Only http(s) URLs are accepted.
|
|
40
|
-
"""
|
|
41
|
-
from d365fo_agent.mcp_server import default_knowledge_db
|
|
42
|
-
|
|
43
|
-
dest = Path(dest) if dest else default_knowledge_db()
|
|
44
|
-
url = url or DEFAULT_KNOWLEDGE_URL
|
|
45
|
-
if not url:
|
|
46
|
-
return {
|
|
47
|
-
"ok": False,
|
|
48
|
-
"error": "No knowledge URL configured. Pass --url <release asset .db/.db.gz>, or build "
|
|
49
|
-
"your own with: d365fo-agent build-index --db <out.db> --packages-root <your "
|
|
50
|
-
"D365 PackagesLocalDirectory> --rebuild",
|
|
51
|
-
}
|
|
52
|
-
if not (url.startswith("http://") or url.startswith("https://")):
|
|
53
|
-
return {"ok": False, "error": f"Refusing non-http(s) URL: {url}"}
|
|
54
|
-
if dest.exists() and not force:
|
|
55
|
-
return {"ok": True, "skipped": True, "dest": str(dest),
|
|
56
|
-
"note": "knowledge index already present (use --force to re-download)"}
|
|
57
|
-
|
|
58
|
-
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
59
|
-
tmp = dest.with_name(dest.name + ".part")
|
|
60
|
-
with opener(url) as response, open(tmp, "wb") as out: # noqa: S310 - scheme checked above
|
|
61
|
-
shutil.copyfileobj(response, out)
|
|
62
|
-
|
|
63
|
-
if url.endswith(".gz") or _is_gzip(tmp):
|
|
64
|
-
with gzip.open(tmp, "rb") as gz, open(dest, "wb") as out:
|
|
65
|
-
shutil.copyfileobj(gz, out)
|
|
66
|
-
tmp.unlink()
|
|
67
|
-
else:
|
|
68
|
-
tmp.replace(dest)
|
|
69
|
-
|
|
70
|
-
return {"ok": True, "dest": str(dest), "bytes": dest.stat().st_size, "source": url}
|
|
1
|
+
"""Download a prebuilt standard-D365 knowledge index into the local cache.
|
|
2
|
+
|
|
3
|
+
This is what lets the MCP server help with X++ development WITHOUT the user re-indexing a full
|
|
4
|
+
repo every time: the standard D365 corpus is the same for everyone, so it is indexed once and
|
|
5
|
+
published as a release asset. ``fetch-knowledge`` downloads it to ``~/.d365fo-agent/d365fo.db``
|
|
6
|
+
(a ``.gz`` asset is decompressed on the fly). The user's own custom code stays optional
|
|
7
|
+
(``--repo-root``). Standard-library only (``urllib`` + ``gzip``).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import gzip
|
|
13
|
+
import shutil
|
|
14
|
+
import urllib.request
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
# Published location of the standard-D365 knowledge index (a SQLite .db or .db.gz). The asset is
|
|
18
|
+
# decoupled from the code version (tag `knowledge-v1`) so wheel releases don't re-upload 100 MB.
|
|
19
|
+
# Override with --url, or build your own from a PLD when the asset is unavailable.
|
|
20
|
+
DEFAULT_KNOWLEDGE_URL = (
|
|
21
|
+
"https://github.com/dbru540/d365fo-agent-developer/releases/download/knowledge-v1/d365fo-standard.db.gz"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _is_gzip(path: Path) -> bool:
|
|
26
|
+
with open(path, "rb") as handle:
|
|
27
|
+
return handle.read(2) == b"\x1f\x8b"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def fetch_knowledge(
|
|
31
|
+
url: str | None = None,
|
|
32
|
+
dest: str | Path | None = None,
|
|
33
|
+
*,
|
|
34
|
+
force: bool = False,
|
|
35
|
+
opener=urllib.request.urlopen,
|
|
36
|
+
) -> dict[str, object]:
|
|
37
|
+
"""Download the knowledge index to ``dest`` (default: the local cache). Returns a result dict.
|
|
38
|
+
|
|
39
|
+
``opener`` is injectable for testing. Only http(s) URLs are accepted.
|
|
40
|
+
"""
|
|
41
|
+
from d365fo_agent.mcp_server import default_knowledge_db
|
|
42
|
+
|
|
43
|
+
dest = Path(dest) if dest else default_knowledge_db()
|
|
44
|
+
url = url or DEFAULT_KNOWLEDGE_URL
|
|
45
|
+
if not url:
|
|
46
|
+
return {
|
|
47
|
+
"ok": False,
|
|
48
|
+
"error": "No knowledge URL configured. Pass --url <release asset .db/.db.gz>, or build "
|
|
49
|
+
"your own with: d365fo-agent build-index --db <out.db> --packages-root <your "
|
|
50
|
+
"D365 PackagesLocalDirectory> --rebuild",
|
|
51
|
+
}
|
|
52
|
+
if not (url.startswith("http://") or url.startswith("https://")):
|
|
53
|
+
return {"ok": False, "error": f"Refusing non-http(s) URL: {url}"}
|
|
54
|
+
if dest.exists() and not force:
|
|
55
|
+
return {"ok": True, "skipped": True, "dest": str(dest),
|
|
56
|
+
"note": "knowledge index already present (use --force to re-download)"}
|
|
57
|
+
|
|
58
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
59
|
+
tmp = dest.with_name(dest.name + ".part")
|
|
60
|
+
with opener(url) as response, open(tmp, "wb") as out: # noqa: S310 - scheme checked above
|
|
61
|
+
shutil.copyfileobj(response, out)
|
|
62
|
+
|
|
63
|
+
if url.endswith(".gz") or _is_gzip(tmp):
|
|
64
|
+
with gzip.open(tmp, "rb") as gz, open(dest, "wb") as out:
|
|
65
|
+
shutil.copyfileobj(gz, out)
|
|
66
|
+
tmp.unlink()
|
|
67
|
+
else:
|
|
68
|
+
tmp.replace(dest)
|
|
69
|
+
|
|
70
|
+
return {"ok": True, "dest": str(dest), "bytes": dest.stat().st_size, "source": url}
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/mcp_server.py
RENAMED
|
@@ -36,13 +36,18 @@ from d365fo_agent.index_store import D365Index
|
|
|
36
36
|
from d365fo_agent.validate import validate_xml
|
|
37
37
|
|
|
38
38
|
PROTOCOL_VERSION = "2025-06-18"
|
|
39
|
-
SERVER_NAME = "d365fo-agent"
|
|
40
|
-
|
|
39
|
+
SERVER_NAME = "d365fo-agent-developer"
|
|
40
|
+
try:
|
|
41
|
+
from importlib.metadata import version as _dist_version
|
|
42
|
+
|
|
43
|
+
SERVER_VERSION = _dist_version("d365fo-agent-developer")
|
|
44
|
+
except Exception: # source tree / not installed
|
|
45
|
+
SERVER_VERSION = "0.0.0-dev"
|
|
41
46
|
|
|
42
47
|
|
|
43
48
|
def _log(message: str) -> None:
|
|
44
49
|
# stdout is the JSON-RPC channel; diagnostics MUST go to stderr.
|
|
45
|
-
print(f"[
|
|
50
|
+
print(f"[{SERVER_NAME}] {message}", file=sys.stderr, flush=True)
|
|
46
51
|
|
|
47
52
|
|
|
48
53
|
class D365MCPServer:
|
|
@@ -799,7 +804,8 @@ def build_server_from_config(
|
|
|
799
804
|
|
|
800
805
|
|
|
801
806
|
def main(argv: list[str] | None = None) -> int:
|
|
802
|
-
parser = argparse.ArgumentParser(prog="d365fo-
|
|
807
|
+
parser = argparse.ArgumentParser(prog="d365fo-agent-developer",
|
|
808
|
+
description="D365 F&O knowledge MCP server (stdio).")
|
|
803
809
|
parser.add_argument("--repo-root", default=os.environ.get("D365FO_REPO_ROOT"))
|
|
804
810
|
parser.add_argument("--rules", default=os.environ.get("D365FO_RULES"))
|
|
805
811
|
parser.add_argument("--db", default=os.environ.get("D365FO_DB"))
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: d365fo-agent-developer
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: Local D365 F&O knowledge toolkit: corpus indexing (SQLite FTS5), deterministic generation, and an MCP server that grounds coding agents (Claude Code, Codex) in real AOT facts.
|
|
5
5
|
Author-email: David Bru <dbru@fiveforty.fr>
|
|
6
6
|
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/dbru540/d365fo-agent
|
|
8
|
-
Project-URL: Repository, https://github.com/dbru540/d365fo-agent
|
|
9
|
-
Project-URL: Issues, https://github.com/dbru540/d365fo-agent/issues
|
|
7
|
+
Project-URL: Homepage, https://github.com/dbru540/d365fo-agent-developer
|
|
8
|
+
Project-URL: Repository, https://github.com/dbru540/d365fo-agent-developer
|
|
9
|
+
Project-URL: Issues, https://github.com/dbru540/d365fo-agent-developer/issues
|
|
10
10
|
Keywords: dynamics-365,d365fo,x++,aot,mcp,model-context-protocol,claude,claude-code,codex,ai,code-generation,rag
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -29,7 +29,7 @@ Requires-Dist: ruff; extra == "dev"
|
|
|
29
29
|
Requires-Dist: build; extra == "dev"
|
|
30
30
|
Dynamic: license-file
|
|
31
31
|
|
|
32
|
-
# d365fo-agent — D365 F&O X++ knowledge for Claude Code & Codex
|
|
32
|
+
# d365fo-agent-developer — D365 F&O X++ knowledge for Claude Code & Codex
|
|
33
33
|
|
|
34
34
|
A local **MCP server** that gives an AI coding agent (Claude Code, Codex, any MCP host) a grounded
|
|
35
35
|
**knowledge base of Dynamics 365 Finance & Operations X++** — so you can develop for D365 quickly
|
|
@@ -51,9 +51,14 @@ compiler.
|
|
|
51
51
|
```bash
|
|
52
52
|
pip install d365fo-agent-developer
|
|
53
53
|
# or, isolated: pipx install d365fo-agent-developer
|
|
54
|
+
# or zero-install, straight from PyPI at launch time: uvx d365fo-agent-developer
|
|
54
55
|
```
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
With `uvx` you can even skip the install entirely — point your MCP client at
|
|
58
|
+
`uvx` with args `["d365fo-agent-developer"]` (e.g. in Claude Desktop's
|
|
59
|
+
`claude_desktop_config.json`) and the latest published server runs on demand.
|
|
60
|
+
|
|
61
|
+
This installs two commands: `d365fo-agent-developer` (the MCP server; `d365fo-mcp` is a short alias) and `d365fo-agent` (the CLI).
|
|
57
62
|
|
|
58
63
|
## Get the knowledge base (once)
|
|
59
64
|
|
|
@@ -84,18 +89,18 @@ d365fo-agent build-index \
|
|
|
84
89
|
```json
|
|
85
90
|
{
|
|
86
91
|
"mcpServers": {
|
|
87
|
-
"d365fo": { "command": "d365fo-
|
|
92
|
+
"d365fo-agent-developer": { "command": "d365fo-agent-developer", "args": [] }
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
```
|
|
91
96
|
|
|
92
|
-
…or one command: `claude mcp add d365fo d365fo-
|
|
97
|
+
…or one command: `claude mcp add d365fo-agent-developer d365fo-agent-developer`
|
|
93
98
|
|
|
94
99
|
**Codex** — add to `~/.codex/config.toml`:
|
|
95
100
|
|
|
96
101
|
```toml
|
|
97
|
-
[mcp_servers.d365fo]
|
|
98
|
-
command = "d365fo-
|
|
102
|
+
[mcp_servers.d365fo-agent-developer]
|
|
103
|
+
command = "d365fo-agent-developer"
|
|
99
104
|
args = []
|
|
100
105
|
```
|
|
101
106
|
|
|
@@ -109,8 +114,8 @@ Point the server at your D365 source repo so your **custom** classes/tables/EDTs
|
|
|
109
114
|
are indexed too, and so the rich tools can read real signatures and clone real examples:
|
|
110
115
|
|
|
111
116
|
```toml
|
|
112
|
-
[mcp_servers.d365fo]
|
|
113
|
-
command = "d365fo-
|
|
117
|
+
[mcp_servers.d365fo-agent-developer]
|
|
118
|
+
command = "d365fo-agent-developer"
|
|
114
119
|
args = ["--repo-root", "C:/path/to/your/D365Repo",
|
|
115
120
|
"--rules", "C:/path/to/your/rules.json",
|
|
116
121
|
"--packages-root", "C:/AOSService/PackagesLocalDirectory"]
|
|
@@ -127,7 +132,8 @@ args = ["--repo-root", "C:/path/to/your/D365Repo",
|
|
|
127
132
|
`element_exists`, `find_element`, `search_corpus`, `get_signature`, `get_extension_chain`,
|
|
128
133
|
`get_security_links`, `get_entity_exposure`, `find_similar_examples`, `scaffold_object`,
|
|
129
134
|
`find_references`, `find_reverse_references`, `analyze_spec`, `generate_from_spec`, `validate_xml`,
|
|
130
|
-
`lint_artifact`, `derive_entity`, `wire_security`, `compile_model`, `
|
|
135
|
+
`lint_artifact`, `derive_entity`, `wire_security`, `compile_model`, `compile_generated`,
|
|
136
|
+
`get_sql_model`, `explore_functional_unit`, `find_relations`, `get_methodology`, `index_stats`.
|
|
131
137
|
|
|
132
138
|
See [docs/mcp-server.md](docs/mcp-server.md) for the verify-driven workflow and
|
|
133
139
|
[docs/x++-methodology.md](docs/x++-methodology.md) for the behavioural contract.
|
|
@@ -463,7 +463,7 @@ class McpServerTests(unittest.TestCase):
|
|
|
463
463
|
|
|
464
464
|
def test_initialize(self) -> None:
|
|
465
465
|
resp = self._rpc("initialize", {"protocolVersion": "2025-06-18", "capabilities": {}})
|
|
466
|
-
self.assertEqual(resp["result"]["serverInfo"]["name"], "d365fo-agent")
|
|
466
|
+
self.assertEqual(resp["result"]["serverInfo"]["name"], "d365fo-agent-developer")
|
|
467
467
|
self.assertIn("tools", resp["result"]["capabilities"])
|
|
468
468
|
|
|
469
469
|
def test_tools_list_nonempty(self) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/aot_relations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/data/x++-rules.json
RENAMED
|
File without changes
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/entity_derive.py
RENAMED
|
File without changes
|
|
File without changes
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/graph_query.py
RENAMED
|
File without changes
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/graphify_runner.py
RENAMED
|
File without changes
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/index_store.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/security_wiring.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{d365fo_agent_developer-0.6.0 → d365fo_agent_developer-0.6.2}/src/d365fo_agent/type_profile.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|