Skip to content

fix: improve n8n MCP client compatibility with JSON Schema types#61

Merged
abubnalitic-nbl merged 10 commits into
mainfrom
fix/n8n-type-compatibility
Apr 20, 2026
Merged

fix: improve n8n MCP client compatibility with JSON Schema types#61
abubnalitic-nbl merged 10 commits into
mainfrom
fix/n8n-type-compatibility

Conversation

@abubnalitic-nbl

@abubnalitic-nbl abubnalitic-nbl commented Jan 8, 2026

Copy link
Copy Markdown
Contributor

This fix addresses issue #58 where n8n AI Agent encounters errors when connecting to the netbox-mcp-server. The error "can't access property 'inputType', mapTypes[type] is undefined" occurs because n8n isn't flexible with the types. See issue: n8n-io/n8n#19835 (comment)

Raised by @jcollins313 and @DharmaBytesX
Additional input from @X-Coder
Fixes #58

Also fixed the ruff in the main dependencies (it's in dev)

   client compatibility with JSON Schema types

   This fix addresses issue #58 where n8n AI Agent encounters errors when
   connecting to the netbox-mcp-server. The error cant access property
   inputType, mapTypes[type] is undefined" occurs because n8n doesnt

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR attempts to improve n8n MCP client compatibility by modifying type annotations to work around n8n's strict JSON Schema type requirements. The changes include converting parameter types from int to float, changing optional parameters from None defaults to empty string/list defaults, and adding more specific type annotations (dict[str, Any]).

Key changes:

  • Parameter types changed from int to float for limit, offset, and object_id (with internal conversion back to int)
  • Optional parameters changed from None defaults to empty defaults ([] for lists, "" for strings)
  • Type annotations made more specific (dictdict[str, Any])

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py Outdated
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py Outdated
Comment thread src/netbox_mcp_server/server.py Outdated
Comment thread src/netbox_mcp_server/server.py
abubnalitic-nbl and others added 3 commits January 28, 2026 12:23
   use string types for n8n MCP client compatibility

   n8n's MCP client only supports string, number, boolean, and json types
   in its UI. Parameters using dict (object) or list (array) types caused
   'Cannot read properties of undefined (reading 'inputType')' errors.

   Changed parameter signatures to use string types while maintaining
   backward compatibility through helper functions that accept both
   string and native Python types.

   Fixes #58
Handle whitespace, "undefined", "null", and "none" string values
that some MCP clients may pass for empty optional parameters.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Python 3.14-alpine lacks pre-built wheels for pydantic-core, causing
the build to attempt compilation from source which requires Rust.
Python 3.13-alpine has pre-built musllinux wheels available.

Co-Authored-By: Claude Opus 4.5 <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated 14 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/netbox_mcp_server/server.py Outdated
Comment thread pyproject.toml
Comment thread tests/test_ordering.py Outdated
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py Outdated
abubnalitic-nbl and others added 2 commits January 28, 2026 14:14
Restores Python 3.14 Dockerfile and pydantic-core 2.41.5 lockfile.
The older lockfile had pydantic-core 2.33.2 which lacks Python 3.14
musllinux wheels, causing CI build failures.

Co-Authored-By: Claude Opus 4.5 <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/netbox_mcp_server/server.py
Comment thread tests/test_param_parsing.py
Comment thread src/netbox_mcp_server/server.py
Comment thread tests/test_ordering.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
Comment thread src/netbox_mcp_server/server.py
abubnalitic-nbl and others added 2 commits April 20, 2026 10:17
…tests

Add comment blocks at each float annotation (limit, offset, object_id) so
future contributors don't revert to int — the workaround exists because
n8n's mapTypes table has no entry for JSON Schema "integer". Clarify helper
docstrings: MCP callers always hit the string path; dict/list branches exist
only for direct Python callers (tests/library use), unreachable via the
MCP boundary because Pydantic rejects non-string inputs.

Add tests/test_mcp_boundary.py. Every other test uses .fn() which bypasses
schema validation. These go through Client.call_tool() — the path real MCP
clients take — and verify: (1) string filters work, (2) dict filters are
rejected, (3) integer limit/object_id from LLM clients is coerced cleanly.

Relates to #58.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Resolve 4 conflicts:
- pyproject.toml: adopt main's fastmcp>=3.2.0,<4 and tightened
  pydantic/pydantic-settings floors; drop `requests` (unused — main's
  stack is httpx-only).
- uv.lock: regenerate via `uv lock` on the merged pyproject.
- tests/test_ordering.py, tests/test_search.py: keep this branch's
  string-only call semantics (the point of #61), and drop `.fn` — in
  fastmcp 3.x, `@mcp.tool` returns the raw function, so the decorated
  name is directly callable. Matches the style main already adopted.

The four MCP-boundary tests from 14655b3 still pass end-to-end: fastmcp
3.x's Client + call_tool API is compatible with how we use it. Full
suite: 93/93 on Python 3.14 + fastmcp 3.2.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@github-actions

Copy link
Copy Markdown
Contributor

Vulnerability Scan: Passed

Image: netbox-mcp-server:scan

No vulnerabilities found.

Commit: 0bb2909

@abubnalitic-nbl abubnalitic-nbl merged commit d6f4c12 into main Apr 20, 2026
14 of 18 checks passed
@abubnalitic-nbl abubnalitic-nbl deleted the fix/n8n-type-compatibility branch April 20, 2026 15:49
abubnalitic-nbl added a commit that referenced this pull request Apr 21, 2026
- netbox_get_objects.ordering widened back to str | list[str] | None
  (pre-#61 accepted the list form; initial compat-flag work narrowed it)
- Expand _NETBOX_GET_OBJECTS_DESCRIPTION with the full pre-#61 Returns/
  limit/offset/ordering guidance; fix the two-step pattern example to
  reference sites[0]['id'] instead of a hardcoded 1
- Promote the full pre-#61 changelogs docstring to
  _NETBOX_GET_CHANGELOGS_DESCRIPTION, wired into both strict and
  compat tool registrations so LLM clients see the same reference
  material in either mode

Also prune three low-signal tests added earlier on this branch:
- test_search_objects_strict_mode_accepts_lists (covered by pre-existing
  direct-call tests in test_search.py)
- test_impl_parity.py case 4 (ordering — no transformation, identical
  kwargs in both modes)
- test_ordering_empty_list_omits_parameter (empty list collapses to the
  same impl branch as existing "omit" tests)

Add test_ordering_list_joined_comma_separated to guard the restored
ordering list-input surface.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
abubnalitic-nbl added a commit that referenced this pull request Apr 21, 2026
abubnalitic-nbl added a commit that referenced this pull request Apr 22, 2026
Restore signatures, docstrings, Field defaults, description strings, and
in-body comments that drifted from pre-revert origin/main during the
feat/n8n-compat-optin refactor. The strict-mode wrappers now differ from
main only where the dual-mode pattern requires: decorator stripped, body
delegates to the private _impl function, '-> Any' return annotation added.

Restored items:
- Field(default=5, ge=1, le=100) / Field(default=0, ge=0) on limit / offset
- filters: dict (required) on netbox_get_objects and netbox_get_changelogs
- ordering: str | list[str] | None = None on netbox_get_objects
- netbox_get_object_by_id: full fields docstring with IMPORTANT note,
  token-reduction notes, and per-type examples
- netbox_get_changelogs: full docstring listing every filter option
- _NETBOX_GET_OBJECTS_DESCRIPTION: single-quoted dict examples,
  'Optional list of specific fields', 'dict of filters', and main's
  ordering paragraph verbatim
- _NETBOX_SEARCH_OBJECTS_DESCRIPTION: formatted default list, IT IS
  STRONGLY RECOMMENDED note, three Example blocks, Returns section
- In-body comments inside _netbox_*_impl functions (# Validate object_type
  exists in mapping, # Build params with pagination, # Make API call, etc.)

Also:
- test_tool_registration.py: strict-mode assertion changes from
  {'object', 'null'} to {'object'} since filters is no longer nullable.

No behavior change for strict-mode users: these were all documentation
and style restorations or signature shapes that were already honored by
the runtime (ordering's list handling was dead relative to the typed
signature; now signature and runtime agree).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error when connecting to containerized netbox-mcp-server

3 participants