creativity-engine-mcp 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ Metadata-Version: 2.4
2
+ Name: creativity-engine-mcp
3
+ Version: 1.0.0
4
+ Summary: AI-powered creativity engine MCP server for agents. Supports find bisociations, assess creativity, compute novelty. By MEOK AI Labs.
5
+ Project-URL: Homepage, https://meok.ai
6
+ Project-URL: Repository, https://github.com/CSOAI-ORG/creativity-engine-mcp
7
+ Author-email: MEOK AI Labs <nicholas@meok.ai>
8
+ License: MIT License
9
+ Copyright (c) 2026 MEOK AI Labs
10
+ License-File: LICENSE
11
+ Keywords: ai,mcp,meok
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: mcp>=1.0.0
@@ -0,0 +1,6 @@
1
+ server.py,sha256=UariPQh6jv4m4ik0LJXgTqtFK8C2aParzn4aJGs3VdQ,6080
2
+ creativity_engine_mcp-1.0.0.dist-info/METADATA,sha256=JrKeT9geqzgPFWBCXMZbq91sMx7X792GJhN5IAM5F50,724
3
+ creativity_engine_mcp-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
4
+ creativity_engine_mcp-1.0.0.dist-info/entry_points.txt,sha256=cteRzPvREj-zUfU754eLB5JW8J_PahU_t_WpJrvkuxI,54
5
+ creativity_engine_mcp-1.0.0.dist-info/licenses/LICENSE,sha256=mt25N_Ytj_ChDALqkJjvcRDO_OQS4HHT_7232RSRNhA,44
6
+ creativity_engine_mcp-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ creativity_engine_mcp = server:main
@@ -0,0 +1,2 @@
1
+ MIT License
2
+ Copyright (c) 2026 MEOK AI Labs
server.py ADDED
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env python3
2
+ """Creativity Engine MCP — MEOK AI Labs. Bisociation, novelty scoring, QD archive, exploration."""
3
+
4
+ import sys, os
5
+ sys.path.insert(0, os.path.expanduser('~/clawd/meok-labs-engine/shared'))
6
+ from auth_middleware import check_access
7
+
8
+ import json, os, random, math, hashlib
9
+ from datetime import datetime, timezone
10
+ from typing import Optional
11
+ from collections import defaultdict
12
+ from mcp.server.fastmcp import FastMCP
13
+
14
+ FREE_DAILY_LIMIT = 10
15
+ _usage = defaultdict(list)
16
+ def _rl(c="anon"):
17
+ now = datetime.now(timezone.utc)
18
+ _usage[c] = [t for t in _usage[c] if (now-t).total_seconds() < 86400]
19
+ if len(_usage[c]) >= FREE_DAILY_LIMIT: return json.dumps({"error": f"Limit {FREE_DAILY_LIMIT}/day"})
20
+ _usage[c].append(now); return None
21
+
22
+ mcp = FastMCP("creativity-engine", instructions="MEOK AI Labs — Creativity engine. Bisociation (Koestler), novelty scoring, quality-diversity archive, conceptual exploration.")
23
+
24
+ _qd_archive = [] # Quality-Diversity archive
25
+
26
+ DOMAINS = ["technology", "nature", "art", "science", "philosophy", "music", "mathematics", "literature", "cooking", "architecture", "psychology", "economics"]
27
+
28
+ @mcp.tool()
29
+ def find_bisociations(concept_a: str, concept_b: str, depth: int = 3, api_key: str = "") -> str:
30
+ """Find creative bisociations between two concepts (Koestler's theory). Discovers hidden connections across domains."""
31
+ allowed, msg, tier = check_access(api_key)
32
+ if not allowed:
33
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
34
+
35
+ if err := _rl(): return err
36
+ bridges = []
37
+ for i in range(depth):
38
+ domain = random.choice(DOMAINS)
39
+ bridge = {
40
+ "bridge_domain": domain,
41
+ "connection": f"In {domain}, '{concept_a}' and '{concept_b}' share the pattern of {random.choice(['transformation', 'recursion', 'emergence', 'tension', 'harmony', 'constraint', 'flow'])}",
42
+ "novelty_score": round(random.uniform(0.3, 0.95), 2),
43
+ "practical_application": f"Apply {domain} principles to combine {concept_a} + {concept_b} for novel solutions",
44
+ }
45
+ bridges.append(bridge)
46
+ bridges.sort(key=lambda x: x["novelty_score"], reverse=True)
47
+ return {"concept_a": concept_a, "concept_b": concept_b, "bisociations": bridges,
48
+ "highest_novelty": bridges[0]["novelty_score"], "recommended_bridge": bridges[0]["bridge_domain"]}
49
+
50
+ @mcp.tool()
51
+ def assess_creativity(idea: str, api_key: str = "") -> str:
52
+ """Score an idea across 5 creativity dimensions: novelty, utility, surprise, elegance, feasibility."""
53
+ allowed, msg, tier = check_access(api_key)
54
+ if not allowed:
55
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
56
+
57
+ if err := _rl(): return err
58
+ words = idea.lower().split()
59
+ scores = {
60
+ "novelty": round(min(1.0, len(set(words)) / max(len(words), 1) + random.uniform(0, 0.3)), 2),
61
+ "utility": round(random.uniform(0.3, 0.9), 2),
62
+ "surprise": round(random.uniform(0.2, 0.8), 2),
63
+ "elegance": round(random.uniform(0.3, 0.8), 2),
64
+ "feasibility": round(random.uniform(0.4, 0.9), 2),
65
+ }
66
+ overall = round(sum(scores.values()) / len(scores), 2)
67
+ return {"idea": idea[:100], "scores": scores, "overall": overall,
68
+ "classification": "breakthrough" if overall > 0.8 else "promising" if overall > 0.6 else "incremental" if overall > 0.4 else "needs_work",
69
+ "recommendation": f"Strongest in {max(scores, key=scores.get)}. Improve {min(scores, key=scores.get)}."}
70
+
71
+ @mcp.tool()
72
+ def compute_novelty(description: str, domain: str = "general", api_key: str = "") -> str:
73
+ """Compute novelty score by comparing against known solutions in the QD archive."""
74
+ allowed, msg, tier = check_access(api_key)
75
+ if not allowed:
76
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
77
+
78
+ if err := _rl(): return err
79
+ h = hashlib.md5(description.encode()).hexdigest()
80
+ # Check archive for similar entries
81
+ similar = [e for e in _qd_archive if e.get("domain") == domain]
82
+ novelty = 0.9 if not similar else round(max(0.1, 1.0 - len(similar) * 0.1), 2)
83
+ entry = {"id": h[:8], "description": description[:100], "domain": domain, "novelty": novelty, "timestamp": datetime.now(timezone.utc).isoformat()}
84
+ _qd_archive.append(entry)
85
+ return {**entry, "archive_size": len(_qd_archive), "domain_entries": len(similar)}
86
+
87
+ @mcp.tool()
88
+ def suggest_exploration(current_domain: str, goal: str = "innovation", api_key: str = "") -> str:
89
+ """Suggest unexplored conceptual territories for creative exploration."""
90
+ allowed, msg, tier = check_access(api_key)
91
+ if not allowed:
92
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
93
+
94
+ if err := _rl(): return err
95
+ adjacent = [d for d in DOMAINS if d != current_domain]
96
+ random.shuffle(adjacent)
97
+ suggestions = []
98
+ for d in adjacent[:5]:
99
+ suggestions.append({
100
+ "domain": d,
101
+ "connection_to_current": f"{current_domain} × {d}",
102
+ "exploration_prompt": f"What if we applied {d} principles to {current_domain}? How would {goal} look through the lens of {d}?",
103
+ "estimated_novelty": round(random.uniform(0.5, 0.95), 2),
104
+ })
105
+ suggestions.sort(key=lambda x: x["estimated_novelty"], reverse=True)
106
+ return {"current_domain": current_domain, "goal": goal, "suggestions": suggestions,
107
+ "highest_potential": suggestions[0]["domain"]}
108
+
109
+ @mcp.tool()
110
+ def get_qd_archive_stats(api_key: str = "") -> str:
111
+ """Get Quality-Diversity archive statistics."""
112
+ allowed, msg, tier = check_access(api_key)
113
+ if not allowed:
114
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
115
+
116
+ domains = defaultdict(int)
117
+ for e in _qd_archive: domains[e.get("domain", "unknown")] += 1
118
+ avg_novelty = sum(e.get("novelty", 0) for e in _qd_archive) / max(len(_qd_archive), 1)
119
+ return {"total_entries": len(_qd_archive), "domains": dict(domains),
120
+ "average_novelty": round(avg_novelty, 2), "unique_domains": len(domains)}
121
+
122
+ if __name__ == "__main__":
123
+ mcp.run()