#
tokens: 3512/50000 10/10 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .gitignore
├── .idea
│   ├── .gitignore
│   ├── inspectionProfiles
│   │   └── profiles_settings.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── new_relic.iml
│   └── vcs.xml
├── .python-version
├── app.py
├── pyproject.toml
├── README.md
└── uv.lock
```

# Files

--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------

```
1 | 3.13
2 | 
```

--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------

```
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | 
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Python-generated files
 2 | __pycache__/
 3 | *.py[oc]
 4 | build/
 5 | dist/
 6 | wheels/
 7 | *.egg-info
 8 | 
 9 | # Virtual environments
10 | .venv
11 | ./.gitignore
12 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/ivlad003-mcp-newrelic-badge.png)](https://mseep.ai/app/ivlad003-mcp-newrelic)
  2 | 
  3 | # New Relic MCP Server
  4 | 
  5 | A simple Model Context Protocol (MCP) server for querying New Relic logs using NRQL queries. This server enables Large Language Models (LLMs) like Claude to interact with your New Relic data.
  6 | 
  7 | ## Features
  8 | 
  9 | - Query New Relic logs and metrics using NRQL
 10 | - Detailed error logging
 11 | - Easy integration with Claude Desktop
 12 | - Human-readable output formatting
 13 | - Configurable New Relic account ID
 14 | 
 15 | ## Setup Instructions
 16 | 
 17 | ### Prerequisites
 18 | 
 19 | - Python 3.10 or higher
 20 | - New Relic account and API key
 21 | - Claude Desktop application
 22 | 
 23 | ### Installation Steps
 24 | 
 25 | 1. Install `uv` package manager:
 26 | ```bash
 27 | # On macOS/Linux
 28 | curl -LsSf https://astral.sh/uv/install.sh | sh
 29 | 
 30 | # On Windows (PowerShell)
 31 | powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
 32 | ```
 33 | 
 34 | 2. Create and setup project:
 35 | ```bash
 36 | # Create directory
 37 | mkdir newrelic-mcp
 38 | cd newrelic-mcp
 39 | 
 40 | # Create virtual environment
 41 | uv venv
 42 | 
 43 | # Activate virtual environment
 44 | source .venv/bin/activate  # On Unix/macOS
 45 | .venv\Scripts\activate     # On Windows
 46 | 
 47 | # Install dependencies
 48 | uv pip install "mcp[cli]" httpx
 49 | ```
 50 | 
 51 | 3. Create server file `newrelic_logs_server.py` with the provided code.
 52 | 
 53 | 4. Configure your environment variables:
 54 | ```bash
 55 | # On Unix/macOS
 56 | export NEW_RELIC_API_KEY="your-api-key-here"
 57 | export NEW_RELIC_ACCOUNT_ID="your-account-id-here"
 58 | 
 59 | # On Windows (CMD)
 60 | set NEW_RELIC_API_KEY=your-api-key-here
 61 | set NEW_RELIC_ACCOUNT_ID=your-account-id-here
 62 | 
 63 | # On Windows (PowerShell)
 64 | $env:NEW_RELIC_API_KEY = "your-api-key-here"
 65 | $env:NEW_RELIC_ACCOUNT_ID = "your-account-id-here"
 66 | ```
 67 | 
 68 | ### Claude Desktop Integration
 69 | 
 70 | Configure Claude Desktop by editing your configuration file:
 71 | 
 72 | - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
 73 | - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
 74 | 
 75 | Add the following configuration:
 76 | ```json
 77 | {
 78 |     "mcpServers": {
 79 |         "newrelic": {
 80 |             "command": "uv",
 81 |             "args": [
 82 |                 "--directory",
 83 |                 "/absolute/path/to/newrelic-mcp",
 84 |                 "run",
 85 |                 "newrelic_logs_server.py"
 86 |             ],
 87 |             "env": {
 88 |                 "NEW_RELIC_API_KEY": "your-api-key-here",
 89 |                 "NEW_RELIC_ACCOUNT_ID": "your-account-id-here"
 90 |             }
 91 |         }
 92 |     }
 93 | }
 94 | ```
 95 | 
 96 | ## Usage
 97 | 
 98 | ### Example NRQL Queries
 99 | 
100 | 1. Basic Transaction Query:
101 | ```sql
102 | SELECT * FROM Transaction SINCE 1 hour ago
103 | ```
104 | 
105 | 2. Error Analysis:
106 | ```sql
107 | SELECT * FROM Transaction WHERE error IS TRUE SINCE 1 hour ago LIMIT 10
108 | ```
109 | 
110 | 3. Performance Analysis:
111 | ```sql
112 | SELECT average(duration) FROM Transaction FACET name ORDER BY average(duration) DESC LIMIT 5
113 | ```
114 | 
115 | ### Example Claude Prompts
116 | 
117 | You can ask Claude questions like:
118 | - "Show me all transactions from the last hour"
119 | - "Are there any errors in our application?"
120 | - "What are our slowest endpoints?"
121 | 
122 | ## Debugging
123 | 
124 | ### Viewing Logs
125 | 
126 | ```bash
127 | # On macOS/Linux
128 | tail -f ~/Library/Logs/Claude/mcp-server-newrelic.log
129 | 
130 | # On Windows
131 | type %APPDATA%\Claude\logs\mcp-server-newrelic.log
132 | ```
133 | 
134 | ### Testing with MCP Inspector
135 | 
136 | Test your server functionality using:
137 | ```bash
138 | npx @modelcontextprotocol/inspector uv run newrelic_logs_server.py
139 | ```
140 | 
141 | ### Common Issues
142 | 
143 | 1. Authentication Errors:
144 | - Check if NEW_RELIC_API_KEY is set correctly
145 | - Verify API key has correct permissions
146 | - Ensure API key is valid
147 | 
148 | 2. Query Errors:
149 | - Verify NRQL syntax
150 | - Check account ID in code matches your account
151 | - Ensure queried data exists in the time range
152 | 
153 | 3. Connection Issues:
154 | - Check network connectivity
155 | - Verify GraphQL endpoint is accessible
156 | - Ensure no firewalls are blocking connections
157 | 
158 | ## Security Notes
159 | 
160 | - Never commit API keys to version control
161 | - Use environment variables for sensitive data
162 | - Keep dependencies updated
163 | - Monitor query patterns and access logs
164 | 
165 | ## Development
166 | 
167 | ### Local Testing
168 | 
169 | 1. Set environment variables:
170 | ```bash
171 | export NEW_RELIC_API_KEY="your-api-key-here"
172 | export NEW_RELIC_ACCOUNT_ID="your-account-id-here"
173 | ```
174 | 
175 | 2. Run the server:
176 | ```bash
177 | uv run newrelic_logs_server.py
178 | ```
179 | 
180 | ### Code Structure
181 | 
182 | The server implements:
183 | - Single NRQL query tool
184 | - Configurable New Relic account ID
185 | - Comprehensive error handling
186 | - Detailed logging
187 | - Response formatting
188 | 
189 | ### Testing Changes
190 | 
191 | 1. Modify code as needed
192 | 2. Test with MCP Inspector
193 | 3. Restart Claude Desktop to apply changes
194 | 
195 | ## Troubleshooting Guide
196 | 
197 | 1. Server Not Starting:
198 | - Check Python version
199 | - Verify all dependencies are installed
200 | - Ensure virtual environment is activated
201 | 
202 | 2. Query Not Working:
203 | - Check logs for detailed error messages
204 | - Verify NRQL syntax
205 | - Ensure data exists in queried time range
206 | 
207 | 3. Claude Not Connecting:
208 | - Verify configuration file syntax
209 | - Check paths are absolute
210 | - Restart Claude Desktop
211 | 
212 | ## Contributing
213 | 
214 | 1. Fork the repository
215 | 2. Create a feature branch
216 | 3. Submit a pull request
217 | 
218 | ## License
219 | 
220 | This project is licensed under the MIT License.
221 | 
222 | ## Support
223 | 
224 | If you encounter issues:
225 | 1. Check the logs
226 | 2. Review common issues section
227 | 3. Test with MCP Inspector
228 | 4. File an issue on GitHub
```

--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------

```
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <project version="4">
3 |   <component name="VcsDirectoryMappings">
4 |     <mapping directory="" vcs="Git" />
5 |   </component>
6 | </project>
```

--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------

```
1 | <component name="InspectionProjectProfileManager">
2 |   <settings>
3 |     <option name="USE_PROJECT_PROFILE" value="false" />
4 |     <version value="1.0" />
5 |   </settings>
6 | </component>
```

--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------

```toml
 1 | [project]
 2 | name = "mcp-newrelic"
 3 | version = "0.1.0"
 4 | description = "Add your description here"
 5 | readme = "README.md"
 6 | requires-python = ">=3.13"
 7 | dependencies = [
 8 |     "httpx>=0.28.1",
 9 |     "mcp[cli]>=1.2.0",
10 |     "pydantic>=2.10.5",
11 | ]
12 | 
```

--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------

```
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <project version="4">
3 |   <component name="ProjectModuleManager">
4 |     <modules>
5 |       <module fileurl="file://$PROJECT_DIR$/.idea/new_relic.iml" filepath="$PROJECT_DIR$/.idea/new_relic.iml" />
6 |     </modules>
7 |   </component>
8 | </project>
```

--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------

```
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <project version="4">
3 |   <component name="Black">
4 |     <option name="sdkName" value="Python 3.13 (new_relic)" />
5 |   </component>
6 |   <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (new_relic)" project-jdk-type="Python SDK" />
7 | </project>
```

--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------

```python
 1 | import os
 2 | import httpx
 3 | from mcp.server.fastmcp import FastMCP
 4 | import logging
 5 | 
 6 | # Initialize FastMCP server
 7 | mcp = FastMCP("newrelic-logs")
 8 | 
 9 | # Configure logging
10 | logging.basicConfig(level=logging.DEBUG)
11 | logger = logging.getLogger(__name__)
12 | 
13 | # Constants
14 | NR_GRAPHQL_URL = "https://api.newrelic.com/graphql"
15 | DEFAULT_ACCOUNT_ID = os.getenv("NEW_RELIC_ACCOUNT_ID", "1892029")
16 | 
17 | @mcp.tool()
18 | async def query_logs(query: str, account_id: str = DEFAULT_ACCOUNT_ID) -> str:
19 |     """Query New Relic logs using NRQL.
20 | 
21 |     Args:
22 |         query: NRQL query string (e.g., "SELECT * FROM Transaction")
23 |         account_id: New Relic account ID (default from env var)
24 |     """
25 |     graphql_query = f"""
26 |     {{
27 |         actor {{
28 |             account(id: {account_id}) {{
29 |                 nrql(query: "{query}") {{
30 |                     results
31 |                 }}
32 |             }}
33 |         }}
34 |     }}
35 |     """
36 | 
37 |     headers = {
38 |         "Content-Type": "application/json",
39 |         "API-Key": os.getenv("NEW_RELIC_API_KEY")
40 |     }
41 | 
42 |     payload = {
43 |         "query": graphql_query
44 |     }
45 | 
46 |     try:
47 |         async with httpx.AsyncClient() as client:
48 |             response = await client.post(
49 |                 NR_GRAPHQL_URL,
50 |                 headers=headers,
51 |                 json=payload
52 |             )
53 |             response.raise_for_status()
54 |             result = response.json()
55 | 
56 |             # Log the full response content
57 |             logger.debug("Response JSON: %s", result)
58 | 
59 |             # Check for errors in the response
60 |             if "errors" in result:
61 |                 logger.error("GraphQL errors: %s", result["errors"])
62 |                 return f"GraphQL errors: {result['errors']}"
63 | 
64 |             # Extract logs from response
65 |             data = result.get("data")
66 |             if data is None:
67 |                 logger.error("No 'data' field in response")
68 |                 return "Error: No 'data' field in response"
69 | 
70 |             account = data.get("actor", {}).get("account")
71 |             if account is None:
72 |                 logger.error("No 'account' field in 'actor'")
73 |                 return "Error: No 'account' field in 'actor'"
74 | 
75 |             nrql = account.get("nrql")
76 |             if nrql is None:
77 |                 logger.error("No 'nrql' field in 'account'")
78 |                 return "Error: No 'nrql' field in 'account'"
79 | 
80 |             logs = nrql.get("results", [])
81 | 
82 |             # Format the logs into a readable string
83 |             formatted_logs = []
84 |             for log in logs:
85 |                 formatted_logs.append("---\n" + "\n".join(f"{k}: {v}" for k, v in log.items()))
86 | 
87 |             return "\n".join(formatted_logs) if formatted_logs else "No logs found"
88 |     except Exception as e:
89 |         logger.error("Error querying logs: %s", str(e))
90 |         return f"Error querying logs: {str(e)}"
91 | 
92 | 
93 | if __name__ == "__main__":
94 |     mcp.run()
```