get_plugin_dependency_graph
Recursively analyze Jenkins plugin dependencies to leaf nodes and return nodes and edges for Graphviz graph rendering.
Instructions
Get dependency graph for a specific plugin in Graphviz format
Recursively analyzes dependencies down to leaf nodes. Returns nodes and edges that can be used to generate a dependency graph.
Args: short_name: The short name of the plugin to analyze
Returns: A dictionary with 'nodes' and 'edges' for Graphviz rendering
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| short_name | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/mcp_jenkins/server/plugin.py:78-90 (handler)The MCP tool handler function that exposes get_plugin_dependency_graph as a 'read' tool. Delegates to the REST client.
async def get_plugin_dependency_graph(ctx: Context, short_name: str) -> dict: """Get dependency graph for a specific plugin in Graphviz format Recursively analyzes dependencies down to leaf nodes. Returns nodes and edges that can be used to generate a dependency graph. Args: short_name: The short name of the plugin to analyze Returns: A dictionary with 'nodes' and 'edges' for Graphviz rendering """ return jenkins(ctx).get_plugin_dependency_graph(short_name=short_name) - The core implementation of get_plugin_dependency_graph. Recursively traverses plugin dependencies, building nodes and edges for a Graphviz graph.
def get_plugin_dependency_graph(self, short_name: str) -> dict: """Get dependency graph for a specific plugin in Graphviz format. Recursively analyzes dependencies down to leaf nodes (plugins with no dependencies). Args: short_name: The short name of the plugin to analyze. Returns: A dictionary containing 'nodes' and 'edges' for Graphviz rendering. """ plugins = self.get_plugins(depth=2) installed = {p['shortName']: p for p in plugins} if short_name not in installed: return {'nodes': [], 'edges': [], 'error': f'Plugin not found: {short_name}'} nodes = [] edges = [] visited = set() def traverse(name: str) -> None: if name in visited: return visited.add(name) if name not in installed: nodes.append({'id': name, 'label': name, 'status': 'missing'}) return plugin = installed[name] nodes.append( { 'id': name, 'label': f'{name}\n({plugin.get("version", "?")})', 'status': 'installed', } ) deps = plugin.get('dependencies', []) for dep in deps: dep_name = dep.get('shortName', '') edges.append({'from': name, 'to': dep_name}) traverse(dep_name) traverse(short_name) return {'nodes': nodes, 'edges': edges} - src/mcp_jenkins/server/__init__.py:30-34 (registration)The MCP server instance (JenkinsMCP) is created here. The @mcp.tool decorator in plugin.py registers the tool via the 'mcp' instance imported from this module.
mcp = JenkinsMCP('mcp-jenkins', lifespan=lifespan) # Import tool modules to register them with the MCP server # This must happen after mcp is created so the @mcp.tool() decorators can reference it from mcp_jenkins.server import build, item, node, plugin, queue, view # noqa: F401, E402 - Test that validates get_plugin_dependency_graph returns correct nodes and edges for a plugin with dependencies.
async def test_get_plugin_dependency_graph(mock_jenkins, mocker): mock_jenkins.get_plugin_dependency_graph.return_value = { 'nodes': [ {'id': 'plugin-a', 'label': 'plugin-a\n(1.0)', 'status': 'installed'}, {'id': 'dep-a', 'label': 'dep-a\n(1.0)', 'status': 'installed'}, ], 'edges': [{'from': 'plugin-a', 'to': 'dep-a'}], } result = await plugin.get_plugin_dependency_graph(mocker.Mock(), short_name='plugin-a') assert result == { 'nodes': [ {'id': 'plugin-a', 'label': 'plugin-a\n(1.0)', 'status': 'installed'}, {'id': 'dep-a', 'label': 'dep-a\n(1.0)', 'status': 'installed'}, ], 'edges': [{'from': 'plugin-a', 'to': 'dep-a'}], }