v2: Forge Console + Open WebUI artifacts + Docker
- web/: Local chat UI (Express + WS → Codex bridge) - openwebui/: Preset, pipelines, knowledge manifest - Dockerfile + docker-compose.yml - Updated README with 3 frontend options - CLI-agnostic: works with Codex, Claude Code, Kiro, Gemini
This commit is contained in:
54
skills/gainsight-px/SKILL.md
Normal file
54
skills/gainsight-px/SKILL.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: gainsight-px
|
||||
description: Interact directly with the Gainsight PX REST API to fetch user/account data or track events.
|
||||
tools:
|
||||
- name: px_get_user
|
||||
description: Fetch a specific user by their unique identity ID.
|
||||
entry:
|
||||
type: python
|
||||
path: gainsight_px.py
|
||||
args: ["get_user"]
|
||||
- name: px_get_account
|
||||
description: Fetch a specific account by its ID.
|
||||
entry:
|
||||
type: python
|
||||
path: gainsight_px.py
|
||||
args: ["get_account"]
|
||||
- name: px_search_user
|
||||
description: Search for a user in Gainsight PX by their email address.
|
||||
entry:
|
||||
type: python
|
||||
path: gainsight_px.py
|
||||
args: ["search_user"]
|
||||
- name: px_track_event
|
||||
description: Track a custom event for a user in Gainsight PX. Requires user_id, event_name, and optional JSON properties.
|
||||
entry:
|
||||
type: python
|
||||
path: gainsight_px.py
|
||||
args: ["track_event"]
|
||||
---
|
||||
|
||||
# Gainsight PX REST API Skill
|
||||
|
||||
This skill allows agents to natively interface with your Gainsight PX instance without needing an intermediate MCP server like Pipedream or Zapier.
|
||||
|
||||
## Setup
|
||||
|
||||
You must export your API key before using the tools. You can generate an API key from your Gainsight PX Administration -> REST API section.
|
||||
|
||||
```bash
|
||||
# Add this to your environment
|
||||
export GAINSIGHT_PX_API_KEY="your-api-key-here"
|
||||
|
||||
# Optional: If you are in the EU region, set this flag. Default is US.
|
||||
export GAINSIGHT_PX_REGION="EU"
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
It uses a lightweight Python script (`gainsight_px.py`) that implements standard REST endpoints documented by Apiary (`https://api.aptrinsic.com/v1/...`).
|
||||
|
||||
### Capabilities
|
||||
- **Lookups:** Find exactly who a user is by ID or email.
|
||||
- **Account Context:** Pull account metadata.
|
||||
- **Event Injection:** Push arbitrary telemetry events natively.
|
||||
108
skills/gainsight-px/gainsight_px.py
Normal file
108
skills/gainsight-px/gainsight_px.py
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
# Gainsight PX API configuration
|
||||
# Region determines the base URL (US or EU)
|
||||
PX_REGION = os.environ.get("GAINSIGHT_PX_REGION", "US").upper()
|
||||
PX_API_KEY = os.environ.get("GAINSIGHT_PX_API_KEY")
|
||||
|
||||
if PX_REGION == "EU":
|
||||
BASE_URL = "https://eu-api.aptrinsic.com/v1"
|
||||
else:
|
||||
BASE_URL = "https://api.aptrinsic.com/v1"
|
||||
|
||||
def make_request(method, endpoint, data=None):
|
||||
if not PX_API_KEY:
|
||||
print(json.dumps({"error": "GAINSIGHT_PX_API_KEY environment variable is missing."}))
|
||||
sys.exit(1)
|
||||
|
||||
url = f"{BASE_URL}{endpoint}"
|
||||
headers = {
|
||||
"X-APITOKEN": PX_API_KEY,
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json"
|
||||
}
|
||||
|
||||
req_data = None
|
||||
if data:
|
||||
req_data = json.dumps(data).encode("utf-8")
|
||||
|
||||
req = urllib.request.Request(url, data=req_data, headers=headers, method=method)
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(req) as response:
|
||||
return json.loads(response.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as e:
|
||||
err_msg = e.read().decode("utf-8")
|
||||
try:
|
||||
parsed_err = json.loads(err_msg)
|
||||
return {"error": f"HTTP {e.code}", "details": parsed_err}
|
||||
except:
|
||||
return {"error": f"HTTP {e.code}", "details": err_msg}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
def get_user(user_id):
|
||||
"""Retrieve a specific user by their identifyId."""
|
||||
return make_request("GET", f"/users/{user_id}")
|
||||
|
||||
def get_account(account_id):
|
||||
"""Retrieve a specific account by its id."""
|
||||
return make_request("GET", f"/accounts/{account_id}")
|
||||
|
||||
def search_users(email):
|
||||
"""Search for users by email (requires query payload)."""
|
||||
payload = {
|
||||
"filter": {
|
||||
"operator": "AND",
|
||||
"conditions": [
|
||||
{
|
||||
"name": "email",
|
||||
"operator": "EQ",
|
||||
"value": email
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
return make_request("POST", "/users/query", data=payload)
|
||||
|
||||
def track_event(user_id, event_name, properties=None):
|
||||
"""Track a custom event for a specific user."""
|
||||
payload = {
|
||||
"identifyId": user_id,
|
||||
"eventName": event_name,
|
||||
"properties": properties or {}
|
||||
}
|
||||
# Note: tracking usually happens via a different endpoint or batch API,
|
||||
# but for simplicity assuming a standard REST event ingestion if available.
|
||||
return make_request("POST", "/events/custom", data=payload)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(json.dumps({"error": "Missing action. Use: get_user, get_account, search_user, track_event"}))
|
||||
sys.exit(1)
|
||||
|
||||
action = sys.argv[1]
|
||||
|
||||
if action == "get_user" and len(sys.argv) == 3:
|
||||
print(json.dumps(get_user(sys.argv[2]), indent=2))
|
||||
|
||||
elif action == "get_account" and len(sys.argv) == 3:
|
||||
print(json.dumps(get_account(sys.argv[2]), indent=2))
|
||||
|
||||
elif action == "search_user" and len(sys.argv) == 3:
|
||||
print(json.dumps(search_users(sys.argv[2]), indent=2))
|
||||
|
||||
elif action == "track_event" and len(sys.argv) >= 4:
|
||||
user_id = sys.argv[2]
|
||||
event_name = sys.argv[3]
|
||||
props = json.loads(sys.argv[4]) if len(sys.argv) > 4 else {}
|
||||
print(json.dumps(track_event(user_id, event_name, props), indent=2))
|
||||
|
||||
else:
|
||||
print(json.dumps({"error": f"Unknown action or missing arguments: {action}"}))
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user